home *** CD-ROM | disk | FTP | other *** search
/ Young Minds / Young Minds Interactive CD-ROM.ISO / monster / mon.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-12-01  |  218.2 KB  |  9,943 lines

  1. {
  2.  
  3.     This is Monster, a multiuser adventure game system
  4.     where the players create the universe.
  5.  
  6.     Written by Rich Skrenta at Northwestern University, 1988.
  7.  
  8.         skrenta@nuacc.acns.nwu.edu
  9.         skrenta@nuacc.bitnet
  10.  
  11. }
  12.  
  13. program monster(input,output);
  14.  
  15. const
  16.  
  17. %include 'privusers.pas'
  18.  
  19.     veryshortlen = 12;    { very short string length for userid's etc }
  20.     shortlen = 20;        { ordinary short string }
  21.  
  22.     maxobjs = 15;        { max objects allow on floor in a room }
  23.     maxpeople = 10;        { max people allowed in a room }
  24.     maxplayers = 300;    { max log entries to make for players }
  25.     maxcmds = 75;        { top value for cmd keyword slots }
  26.     maxshow = 50;        { top value for set/show keywords }
  27.     maxexit = 6;        { 6 exits from each loc: NSEWUD }
  28.     maxroom = 1000;        { Total maximum ever possible    }
  29.     maxdetail = 5;        { max num of detail keys/descriptions per room }
  30.     maxevent = 15;        { event slots per event block }
  31.     maxindex = 10000;    { top value for bitmap allocation }
  32.     maxhold = 6;        { max # of things a player can be holding }
  33.     maxerr = 15;        { # of consecutive record collisions before the
  34.                   the deadlock error message is printed }
  35.     numevnts = 10;        { # of different event records to be maintained }
  36.     numpunches = 12;    { # of different kinds of punches there are }
  37.     maxparm = 20;        { parms for object USEs }
  38.     maxspells = 50;        { total number of spells available }
  39.  
  40.     descmax = 10;        { lines per description block }
  41.  
  42.  
  43.     DEFAULT_LINE = 32000;    { A virtual one liner record number that
  44.                   really means "use the default one liner
  45.                   description instead of reading one from
  46.                   the file" }
  47.  
  48. { Mnemonics for directions }
  49.  
  50.     north = 1;
  51.     south = 2;
  52.     east = 3;
  53.     west = 4;
  54.     up = 5;
  55.     down = 6;
  56.  
  57.  
  58. { Index record mnemonics }
  59.  
  60.     I_BLOCK = 1;    { True if description block is not used        }
  61.     I_LINE = 2;    { True if line slot is not used            }
  62.     I_ROOM = 3;    { True if room slot is not in use        }
  63.     I_PLAYER = 4;    { True if slot is not occupied by a player    }
  64.     I_ASLEEP = 5;    { True if player is not playing            }
  65.     I_OBJECT = 6;    { True if object record is not being used    }
  66.     I_INT = 7;    { True if int record is not being used        }
  67.  
  68. { Integer record mnemonics }
  69.  
  70.     N_LOCATION = 1;        { Player's location }
  71.     N_NUMROOMS = 2;        { How many rooms they've made }
  72.     N_ALLOW = 3;        { How many rooms they're allowed to make }
  73.     N_ACCEPT = 4;        { Number of open accept exits they have }
  74.     N_EXPERIENCE = 5;    { How "good" they are }
  75.     N_SELF = 6;        { player's self descriptions }
  76.  
  77. { object kind mnemonics }
  78.  
  79.     O_BLAND = 0;        { bland object, good for keys }
  80.     O_WEAPON = 1;
  81.     O_ARMOR = 2;
  82.     O_THRUSTER = 3;        { use puts player through an exit }
  83.     O_CLOAK = 4;
  84.  
  85.     O_BAG = 100;
  86.     O_CRYSTAL = 101;
  87.     O_WAND = 102;
  88.     O_HAND = 103;
  89.  
  90.  
  91. { Command Mnemonics }
  92.     error = 0;
  93.     setnam = 1;
  94.     help = 2;
  95.     quest = 3;
  96.     quit = 4;
  97.     look = 5;
  98.     go = 6;
  99.     form = 7;
  100.     link = 8;
  101.     unlink = 9;
  102.     c_whisper = 10;
  103.     poof = 11;
  104.     desc = 12;
  105.     dbg = 14;
  106.     say = 15;
  107.  
  108.     c_rooms = 17;
  109.     c_system = 18;
  110.     c_disown = 19;
  111.     c_claim = 20;
  112.     c_create = 21;
  113.     c_public = 22;
  114.     c_accept = 23;
  115.     c_refuse = 24;
  116.     c_zap = 25;
  117.     c_hide = 26;
  118.     c_l = 27;
  119.     c_north = 28;
  120.     c_south = 29;
  121.     c_east = 30;
  122.     c_west = 31;
  123.     c_up = 32;
  124.     c_down = 33;
  125.     c_n = 34;
  126.     c_s = 35;
  127.     c_e = 36;
  128.     c_w = 37;
  129.     c_u = 38;
  130.     c_d = 39;
  131.     c_custom = 40;
  132.     c_who = 41;
  133.     c_players = 42;
  134.     c_search = 43;
  135.     c_unhide = 44;
  136.     c_punch = 45;
  137.     c_ping = 46;
  138.     c_health = 47;
  139.     c_get = 48;
  140.     c_drop = 49;
  141.     c_inv = 50;
  142.     c_i = 51;
  143.     c_self = 52;
  144.     c_whois = 53;
  145.     c_duplicate = 54;
  146.  
  147.     c_version = 56;
  148.     c_objects = 57;
  149.     c_use = 58;
  150.     c_wield = 59;
  151.     c_brief = 60;
  152.     c_wear = 61;
  153.     c_relink = 62;
  154.     c_unmake = 63;
  155.     c_destroy = 64;
  156.     c_show = 65;
  157.     c_set = 66;
  158.  
  159.     e_detail = 100;        { pseudo command for log_action of desc exit }
  160.     e_custroom = 101;    { customizing this room }
  161.     e_program = 102;    { customizing (programming) an object }
  162.     e_usecrystal = 103;    { using a crystal ball }
  163.  
  164.  
  165. { Show Mnemonics }
  166.  
  167.     s_exits = 1;
  168.     s_object = 2;
  169.     s_quest = 3;
  170.     s_details = 4;
  171.  
  172.  
  173. { Set Mnemonics }
  174.  
  175.     y_quest = 1;
  176.     y_altmsg = 2;
  177.     y_group1 = 3;
  178.     y_group2 = 4;
  179.  
  180.  
  181. { Event Mnemonics }
  182.  
  183.     E_EXIT = 1;        { player left room            }
  184.     E_ENTER = 2;        { player entered room            }
  185.     E_BEGIN = 3;        { player joined game here        }
  186.     E_QUIT = 4;        { player here quit game            }
  187.     
  188.     E_SAY = 5;        { someone said something        }
  189.     E_SETNAM = 6;        { player set his personal name        }
  190.     E_POOFIN = 8;        { someone poofed into this room        }
  191.     E_POOFOUT = 9;        { someone poofed out of this room    }
  192.     E_DETACH = 10;        { a link has been destroyed        }
  193.     E_EDITDONE = 11;    { someone is finished editing a desc    }
  194.     E_NEWEXIT = 12;        { someone made an exit here        }
  195.     E_BOUNCEDIN = 13;    { an object "bounced" into the room    }
  196.     E_EXAMINE = 14;        { someone is examining something    }
  197.     E_CUSTDONE = 15;    { someone is done customizing an exit    }
  198.     E_FOUND = 16;        { player found something        }
  199.     E_SEARCH = 17;        { player is searching room        }
  200.     E_DONEDET = 18;        { done adding details to a room        }
  201.     E_HIDOBJ = 19;        { someone hid an object here        }
  202.     E_UNHIDE = 20;        { voluntarily revealed themself        }
  203.     E_FOUNDYOU = 21;    { someone found someone else hiding    }
  204.     E_PUNCH = 22;        { someone has punched someone else    }
  205.     E_MADEOBJ = 23;        { someone made an object here        }
  206.     E_GET = 24;        { someone picked up an object        }
  207.     E_DROP = 25;        { someone dropped an object        }
  208.     E_DROPALL = 26;        { quit & dropped stuff on way out    }
  209.     E_IHID = 27;        { tell others that I have hidden (!)    }
  210.     E_NOISES = 28;        { strange noises from hidden people    }
  211.     E_PING = 29;        { send a ping to a potential zombie    }
  212.     E_PONG = 30;        { ping answered                }
  213.     E_HIDEPUNCH = 31;    { someone hidden is attacking        }
  214.     E_SLIPPED = 32;        { attack caused obj to drop unwillingly }
  215.     E_ROOMDONE = 33;    { done customizing this room        }
  216.     E_OBJDONE = 34;        { done programming an object        }
  217.     E_HPOOFOUT = 35;    { someone hiding poofed    out        }
  218.     E_FAILGO = 36;        { a player failed to go through an exit }
  219.     E_HPOOFIN = 37;        { someone poofed into a room hidden    }
  220.     E_TRYPUNCH = 38;    { someone failed to punch someone else    }
  221.     E_PINGONE = 39;        { someone was pinged away . . .        }
  222.     E_CLAIM = 40;        { someone claimed this room        }
  223.     E_DISOWN = 41;        { owner of this room has disowned it    }
  224.     E_WEAKER = 42;        { person is weaker from battle        }
  225.     E_OBJCLAIM = 43;    { someone claimed an object        }
  226.     E_OBJDISOWN = 44;    { someone disowned an object        }
  227.     E_SELFDONE = 45;    { done editing self description        }
  228.     E_WHISPER = 46;        { someone whispers to someone else    }
  229.     E_WIELD = 47;        { player wields a weapon        }
  230.     E_UNWIELD = 48;        { player puts a weapon away        }
  231.     E_DONECRYSTALUSE = 49;    { done using the crystal ball        }
  232.     E_WEAR = 50;        { someone has put on something        }
  233.     E_UNWEAR = 51;        { someone has taken off something    }
  234.     E_DESTROY = 52;        { someone has destroyed an object    }
  235.     E_HIDESAY = 53;        { anonymous say                }
  236.     E_OBJPUBLIC = 54;    { someone made an object public        }
  237.     E_SYSDONE = 55;        { done with system maint. mode        }
  238.     E_UNMAKE = 56;        { remove typedef for object        }
  239.     E_LOOKDETAIL = 57;    { looking at a detail of this room    }
  240.     E_ACCEPT = 58;        { made an "accept" exit here        }
  241.     E_REFUSE = 59;        { got rid of an "accept" exit here    }
  242.     E_DIED = 60;        { someone died and evaporated        }
  243.     E_LOOKYOU = 61;        { someone is looking at you        }
  244.     E_FAILGET = 62;        { someone can't get something        }
  245.     E_FAILUSE = 63;        { someone can't use something        }
  246.     E_CHILL = 64;        { someone scrys you            }
  247.     E_NOISE2 = 65;        { say while in crystal ball        }
  248.     E_LOOKSELF = 66;    { someone looks at themself        }
  249.     E_INVENT = 67;        { someone takes inventory        }
  250.     E_POOFYOU = 68;        { MM poofs someone away . . . .        }
  251.     E_WHO = 69;        { someone does a who            }
  252.     E_PLAYERS = 70;        { someone does a players        }
  253.     E_VIEWSELF = 71;    { someone views a self description    }
  254.     E_REALNOISE = 72;    { make the real noises message print    }
  255.     E_ALTNOISE = 73;    { alternate mystery message        }
  256.     E_MIDNIGHT = 74;    { it's midnight now, tell everyone    }
  257.  
  258.     E_ACTION = 100;        { base command action event }
  259.  
  260.  
  261. { Misc. }
  262.  
  263.     GOODHEALTH = 7;
  264.  
  265.  
  266. type
  267.     string = varying[80] of char;
  268.     veryshortstring = varying[veryshortlen] of char;
  269.     shortstring = varying[shortlen] of char;
  270.  
  271.     { This is a list of description block numbers;
  272.       If a number is zero, there is no text for that block }
  273.     
  274.  
  275.     { exit kinds:
  276.         0: no way - blocked exit
  277.         1: open passageway
  278.         2: object required
  279.  
  280.         6: exit only exists if player is holding the key
  281.     }
  282.  
  283.     exit = record
  284.         toloc: integer;        { location exit goes to }
  285.         kind: integer;        { type of the exit }
  286.         slot: integer;        { exit slot of toloc target }
  287.  
  288.         exitdesc,  { one liner description of exit  }
  289.         closed,    { desc of a closed door }
  290.         fail,       { description if can't go thru   }
  291.         success,   { desc while going thru exit     }
  292.         goin,      { what others see when you go into the exit }
  293. {        ofail,    }
  294.         comeout:   { what others see when you come out of the exit }
  295.               integer; { all refer to the liner file }
  296.                    { if zero defaults will be printed }
  297.  
  298.         hidden: integer;    { **** about to change this **** }
  299.         objreq: integer;    { object required to pass this exit }
  300.  
  301.         alias: veryshortstring; { alias for the exit dir, a keyword }
  302.  
  303.         reqverb: boolean;    { require alias as a verb to work }
  304.         reqalias: boolean;    { require alias only (no direction) to
  305.                       pass through the exit }
  306.         autolook: boolean;    { do a look when user comes out of exit }
  307.     end;
  308.  
  309.  
  310.     { index record # 1 is block index }
  311.     { index record # 2 is line index }
  312.     { index record # 3 is room index }
  313.     { index record # 4 is player alloc index }
  314.     { index record # 5 is player awake (in game) index }
  315.     indexrec = record
  316.         indexnum: integer;    { validation number }
  317.         free: packed array[1..maxindex] of boolean;
  318.         top: integer;   { max records available }
  319.         inuse: integer; { record #s in use }
  320.     end;
  321.  
  322.  
  323.     { names are record #1   }
  324.     { owners are record # 2 }
  325.     { player pers_names are record # 3 }
  326.     { userids are record # 4 }
  327.     { object names are record # 5 }
  328.     { object creators are record # 6 }
  329.     { date of last play is # 7 }
  330.     { time of last play is # 8 }
  331.     namrec = record
  332.         validate: integer;
  333.         loctop: integer;
  334.         idents: array[1..maxroom] of shortstring;
  335.     end;
  336.  
  337.     objectrec = record
  338.         objnum: integer;    { allocation number for the object }
  339.         onum: integer;        { number index to objnam/objown }
  340.         oname: shortstring;    { duplicate of name of object }
  341.         kind: integer;        { what kind of object this is }
  342.         linedesc: integer;    { liner desc of object Here }
  343.  
  344.         home: integer;        { if object at home, then print the }
  345.         homedesc: integer;    { home description }
  346.  
  347.         actindx: integer;    { action index -- programs for the future }
  348.         examine: integer;    { desc block for close inspection }
  349.         worth: integer;        { how much it cost to make (in gold) }
  350.         numexist: integer;    { number in existence }
  351.  
  352.         sticky: boolean;    { can they ever get it? }
  353.         getobjreq: integer;    { object required to get this object }
  354.         getfail: integer;    { fail-to-get description }
  355.         getsuccess: integer;    { successful picked up description }
  356.  
  357.         useobjreq: integer;    { object require to use this object }
  358.         uselocreq: integer;    { place have to be to use this object }
  359.         usefail: integer;    { fail-to-use description }
  360.         usesuccess: integer;    { successful use of object description }
  361.  
  362.         usealias: veryshortstring;
  363.         reqalias: boolean;
  364.         reqverb: boolean;
  365.  
  366.         particle: integer;    { a,an,some, etc... "particle" is not
  367.                       be right, but hey, it's in the code }
  368.  
  369.         parms: array[1..maxparm] of integer;
  370.  
  371.         d1: integer;        { extra description # 1 }
  372.         d2: integer;        { extra description # 2 }
  373.         exp3,exp4,exp5,exp6: integer;
  374.     end;
  375.  
  376.     anevent = record
  377.         sender,            { slot of sender }
  378.         action,            { what event this is, E_something }
  379.         target,            { opt target of action }
  380.         parm: integer;        { expansion parm }
  381.         msg: string;        { string for SAY and other cmds }
  382.         loc: integer;        { room that event is targeted for }
  383.     end;
  384.  
  385.     eventrec = record
  386.         validat: integer;    { validation number for record locking }
  387.         evnt: array[1..maxevent] of anevent;
  388.         point: integer;        { circular buffer pointer }
  389.     end;
  390.  
  391.     peoplerec = record
  392.         kind: integer;           { 0=none,1=player,2=npc }
  393.         parm: integer;           { index to npc controller (object?) }
  394.  
  395.         username: veryshortstring; { actual userid of person }
  396.         name: shortstring;       { chosen name of person }
  397.         hiding: integer;       { degree to which they're hiding }
  398.         act,targ: integer;       { last thing that this person did }
  399.  
  400.         holding: array[1..maxhold] of integer;    { objects being held }
  401.         experience: integer;
  402.  
  403.         wearing: integer;    { object that they're wearing }
  404.         wielding: integer;    { weapon they're wielding }
  405.         health: integer;    { how healthy they are }
  406.  
  407.         self: integer;        { self description }
  408.  
  409.         ex1,ex2,ex3,ex4,ex5: integer;
  410.     end;
  411.  
  412.     spellrec = record
  413.         recnum: integer;
  414.         level: array[1..maxspells] of integer;
  415.     end;
  416.  
  417.     descrec = record
  418.         descrinum: integer;
  419.         lines: array[1..descmax] of string;
  420.         desclen: integer;  { number used in this block }
  421.     end;
  422.  
  423.     linerec = record
  424.         linenum: integer;
  425.         theline: string;
  426.     end;
  427.  
  428.     room = record
  429.         valid: integer;        { validation number for record locking }
  430.         locnum: integer;
  431.         owner: veryshortstring; { who owns the room: userid if private
  432.                                  '' if public
  433.                                  '*' if disowned }
  434.         nicename: string;    { pretty name for location }
  435.         nameprint: integer;    { code for printing name:
  436.                         0: don't print it
  437.                         1: You're in
  438.                         2: You're at
  439.                     }
  440.  
  441.         primary: integer;    { room descriptions }
  442.         secondary: integer;
  443.         which: integer;        { 0 = only print primary room desc.
  444.                       1 = only print secondary room desc.
  445.                       2 = print both
  446.                       3 = print primary then secondary
  447.                         if has magic object }
  448.  
  449.         magicobj: integer;    { special object for this room }
  450.         effects: integer;
  451.         parm: integer;
  452.  
  453.         exits: array[1..maxexit] of exit;
  454.  
  455.         pile: integer;        { if more than maxobjs objects here }
  456.         objs: array[1..maxobjs] of integer;    { refs to object file }
  457.         objhide: array[1..maxobjs] of integer;    { how much each object
  458.                               is hidden }
  459.                             { see hidden on exitrec
  460.                               above }
  461.  
  462.         objdrop: integer;    { where objects go when they're dropped }
  463.         objdesc: integer;    { what it says when they're dropped }
  464.         objdest: integer;    { what it says in target room when
  465.                       "bounced" object comes in }
  466.  
  467.         people: array[1..maxpeople] of peoplerec;
  468.  
  469.         grploc1,grploc2: integer;
  470.         grpnam1,grpnam2: shortstring;
  471.  
  472.         detail: array[1..maxdetail] of veryshortstring;
  473.         detaildesc: array[1..maxdetail] of integer;
  474.  
  475.         trapto: integer;    { where the "trapdoor" goes }
  476.         trapchance: integer;    { how often the trapdoor works }
  477.  
  478.         rndmsg: integer;    { message that randomly prints }
  479.  
  480.         xmsg2: integer;        { another random block }
  481.         exp2,exp3,exp4: integer;
  482.         exitfail: integer;    { default fail description for exits }
  483.         ofail: integer;        { what other's see when you fail, default }
  484.     end;
  485.  
  486.  
  487.     intrec = record
  488.         intnum: integer;
  489.         int: array[1..maxplayers] of integer;
  490.     end;
  491.  
  492.  
  493. var
  494.     old_prompt: [external] string;
  495.     line:        [external] string;
  496.     oldcmd:    string;        { string for '.' command to do last command }
  497.  
  498.     inmem: boolean;     { Is this rooms roomrec (here....) in memory?
  499.                We call gethere many times to make sure
  500.                here is current.  However, we only want to
  501.                actually do a getroom if the roomrec has been
  502.                modified    }
  503.     brief: boolean := FALSE;    { brief/verbose descriptions }
  504.  
  505.     rndcycle: integer;        { integer for rnd_event }
  506.     debug: boolean;
  507.     ping_answered: boolean;          { flag for ping answers }
  508.     hiding : boolean := FALSE;      { is player hiding? }
  509.     midnight_notyet: boolean := TRUE; { hasn't been midnight yet }
  510.     first_puttoken: boolean := TRUE;  { flag for first place into world }
  511.     logged_act : boolean := FALSE;      { flag to indicate that a log_action
  512.                       has been called, and the next call
  513.                       to clear_command needs to clear the
  514.                       action parms in the here roomrec }
  515.  
  516.     roomfile : file of room;
  517.     eventfile: file of eventrec;
  518.     namfile: file of namrec;
  519.     descfile: file of descrec;
  520.     linefile: file of linerec;
  521.     indexfile: file of indexrec;
  522.     intfile: file of intrec;
  523.     objfile: file of objectrec;
  524.     spellfile: file of spellrec;
  525.  
  526.     cmds: array[1..maxcmds] of shortstring := (
  527.  
  528.         'name',        { setnam = 1    }
  529.         'help',        { help = 2    }
  530.         '?',        { quest = 3    }
  531.         'quit',        { quit = 4    }
  532.         'look',        { look = 5    }
  533.         'go',        { go = 6    }
  534.         'form',        { form = 7    }
  535.         'link',        { link = 8    }
  536.         'unlink',    { unlink = 9    }
  537.         'whisper',    { c_whisper = 10}
  538.         'poof',        { poof = 11    }
  539.         'describe',    { desc = 12    }
  540.         '',
  541.         'debug',    { dbg = 14    }
  542.         'say',        { say = 15    }
  543.         '',        {        }
  544.         'rooms',    { c_rooms = 17    }
  545.         'system',    { c_system = 18    }
  546.         'disown',    { c_disown = 19    }
  547.         'claim',    { c_claim = 20    }
  548.         'make',        { c_create = 21    }
  549.         'public',    { c_public = 22    }
  550.         'accept',    { c_accept = 23    }
  551.         'refuse',    { c_refuse = 24    }
  552.         'zap',        { c_zap = 25    }
  553.         'hide',        { c_hide = 26    }
  554.         'l',        { c_l = 27    }
  555.         'north',    { c_north = 28    }
  556.         'south',    { c_south = 29    }
  557.         'east',        { c_east = 30    }
  558.         'west',        { c_west = 31    }
  559.         'up',        { c_up = 32    }
  560.         'down',        { c_down = 33    }
  561.         'n',        { c_n = 34    }
  562.         's',        { c_s = 35    }
  563.         'e',        { c_e = 36    }
  564.         'w',        { c_w = 37    }
  565.         'u',        { c_u = 38    }
  566.         'd',        { c_d = 39    }
  567.         'customize',    { c_custom = 40    }
  568.         'who',        { c_who = 41    }
  569.         'players',    { c_players = 42}
  570.         'search',    { c_search = 43    }
  571.         'reveal',    { c_unhide = 44    }
  572.         'punch',    { c_punch = 45    }
  573.         'ping',        { c_ping = 46    }
  574.         'health',    { c_health = 47    }
  575.         'get',        { c_get = 48    }
  576.         'drop',        { c_drop = 49    }
  577.         'inventory',    { c_inv = 50    }
  578.         'i',        { c_i = 51    }
  579.         'self',        { c_self = 52    }
  580.         'whois',    { c_whois = 53    }
  581.         'duplicate',    { c_duplicate = 54 }
  582.         '',
  583.         'version',    { c_version = 56}
  584.         'objects',    { c_objects = 57}
  585.         'use',        { c_use = 58    }
  586.         'wield',    { c_wield = 59    }
  587.         'brief',    { c_brief = 60    }
  588.         'wear',        { c_wear = 61    }
  589.         'relink',    { c_relink = 62    }
  590.         'unmake',    { c_unmake = 63    }
  591.         'destroy',    { c_destroy = 64}
  592.         'show',        { c_show = 65    }
  593.         'set',        { c_set = 66    }
  594.         '',
  595.         '',
  596.         '',
  597.         '',
  598.         '',
  599.         '',
  600.         '',
  601.         '',
  602.         ''
  603.     );
  604.  
  605.  
  606.     numcmds: integer;    { number of main level commands there are }
  607.     show: array[1..maxshow] of shortstring;
  608.     numshow: integer;
  609.     setkey: array[1..maxshow] of shortstring;
  610.     numset: integer;
  611.  
  612.     direct: array[1..maxexit] of shortstring :=
  613.         ('north','south','east','west','up','down');
  614.  
  615.     spells: array[1..maxspells] of string;      { names of spells }
  616.     numspells: integer;        { number of spells there actually are }
  617.  
  618.     done: boolean;        { flag for QUIT }
  619.     userid: veryshortstring;    { userid of this player }
  620.     location: integer;    { current place number }
  621.  
  622.     hold_kind: array[1..maxhold] of integer; { kinds of the objects i'm
  623.                            holding }
  624.  
  625.     myslot: integer := 1;    { here.people[myslot]... is this player }
  626.     myname: shortstring;    { personal name this player chose (setname) }
  627.     myevent: integer;    { which point in event buffer we are at }
  628.  
  629.     found_exit: array[1..maxexit] of boolean;
  630.                 { has exit i been found by the player? }
  631.  
  632.     mylog: integer;        { which log entry this player is }
  633.     mywear: integer;    { what I'm wearing }
  634.     mywield: integer;    { weapon I'm wielding }
  635.     myhealth: integer;    { how well I'm feeling }
  636.     myexperience: integer;    { how experienced I am }
  637.     myself: integer;    { self description block }
  638.  
  639.     healthcycle: integer;    { used in rnd_event to control how quickly a
  640.                   player heals }
  641.  
  642.     here: room;        { current room record }
  643.     event: eventrec;
  644.     privd: boolean;
  645.  
  646.     objnam,            { object names }
  647.     objown,            { object owners }
  648.     nam,            { record 1 is room names }
  649.     own,            { rec 2 is room owners }
  650.     pers,            { 3 is player personal names }
  651.     user,            { 4 is player userid    }
  652.     adate,            { 5 is date of last play }
  653.     atime            { 6 is time of last play }
  654.          : namrec;
  655.  
  656.     anint: intrec;        { info about game players }
  657.     obj: objectrec;
  658.     spell: spellrec;
  659.  
  660.     block: descrec;        { a text block of descmax lines }
  661.     indx: indexrec;        { an record allocation record }
  662.     oneliner: linerec;    { a line record }
  663.  
  664.     heredsc: descrec;
  665.  
  666.  
  667. [external]
  668. procedure wait(seconds: real);    { system SLEEP call }
  669. external;
  670.  
  671. [external]
  672. function random:real;    { system random number generator }
  673. external;
  674.  
  675. [external]
  676. function rnd100: integer;    { returns a random # between 0-100 }
  677. external;
  678.  
  679. [external]
  680. procedure setup_guts;    { disables ctrl-Y/ctrl-C }
  681.             { necessary to prevent ZOMBIES in the world }
  682. extern;
  683.  
  684. [external]
  685. procedure finish_guts;    { re-enables ctrl-Y/ctrl-C }
  686. extern;
  687.  
  688. [external] function get_userid:string;
  689. external;
  690.  
  691. [external] function trim(s: string): string;
  692. external;
  693.  
  694. [external]
  695. procedure grab_line(prompt: string; var s:string; echo:boolean := true);
  696. { Input routine.   Gets a line of text from user which checking
  697.   for async events }
  698. external;
  699.  
  700. [external]
  701. procedure putchars(s: string);
  702. extern;
  703.  
  704. procedure xpoof(loc: integer);
  705. forward;
  706.  
  707. procedure do_exit(exit_slot: integer);
  708. forward;
  709.  
  710. function put_token(room: integer;var aslot:integer;hidelev:integer := 0):boolean;
  711. forward;
  712.  
  713. procedure take_token(aslot, roomno: integer);
  714. forward;
  715.  
  716. procedure maybe_drop;
  717. forward;
  718.  
  719. procedure do_program(objnam: string);
  720. forward;
  721.  
  722. function drop_everything(pslot: integer := 0): boolean;
  723. forward;
  724.  
  725.  
  726. procedure collision_wait;
  727. var
  728.     wait_time: real;
  729.  
  730. begin
  731.     wait_time := random;
  732.     if wait_time < 0.001 then
  733.         wait_time := 0.001;
  734.     wait(wait_time);
  735. end;
  736.  
  737.  
  738. { increment err; if err is too high, suspect deadlock }
  739. { this is called by all getX procedures to ease deadlock checking }
  740. procedure deadcheck(var err: integer; s:string);
  741.  
  742. begin
  743.     err := err + 1;
  744.     if err > maxerr then begin
  745.         writeln('%warning- ',s,' seems to be deadlocked; notify the Monster Manager');
  746.         finish_guts;
  747.         halt;
  748.         err := 0;
  749.     end;
  750. end;
  751.  
  752.  
  753.  
  754. { first procedure of form getX
  755.   attempts to get given room record
  756.   resolves record access conflicts, checks for deadlocks
  757.   Locks record; use freeroom immediately after getroom if data is
  758.   for read-only
  759. }
  760. procedure getroom(n: integer:= 0);
  761. var
  762.     err: integer;
  763.  
  764. begin
  765.     if n = 0 then
  766.         n := location;
  767.     roomfile^.valid := 0;
  768.     err := 0;
  769.     if debug then
  770.         writeln('%getroom(',n:1,')');
  771.     find(roomfile,n,error := continue);
  772.     while roomfile^.valid <> n do begin
  773.         deadcheck(err,'getroom');
  774.         collision_wait;
  775.         find(roomfile,n,error := continue);
  776.     end;
  777.     here := roomfile^;
  778.  
  779.     inmem := false;
  780.         { since this getroom could be doing anything, we will
  781.           assume that it is bozoing the correct here record for
  782.           this room.  If this getroom called by gethere, then
  783.           gethere will correct inmem immediately.  Otherwise
  784.           the next gethere will restore the correct here record. }
  785. end;
  786.  
  787. procedure putroom;
  788.  
  789. begin
  790.     locate(roomfile,here.valid);
  791.     roomfile^ := here;
  792.     put(roomfile);
  793. end;
  794.  
  795. procedure freeroom;    { unlock the record if you're not going to write it }
  796.  
  797. begin
  798.     unlock(roomfile);
  799. end;
  800.  
  801. procedure gethere(n: integer := 0);
  802.  
  803. begin
  804.     if (n = 0) or (n = location) then begin
  805.         if not(inmem) then begin
  806.             getroom;    { getroom(n) okay here also }
  807.             freeroom;
  808.             inmem := true;
  809.         end else if debug then
  810.             writeln('%gethere - here already in memory');
  811.     end else begin
  812.         getroom(n);
  813.         freeroom;
  814.     end;
  815. end;
  816.  
  817.  
  818. procedure getown;
  819. var
  820.     err: integer;
  821.  
  822. begin
  823.     namfile^.validate := 0;
  824.     err := 0;
  825.     find(namfile,2,error := continue);
  826.     while namfile^.validate <> 2 do begin
  827.         deadcheck(err,'getown');
  828.         collision_wait;
  829.         find(namfile,2,error := continue);
  830.     end;
  831.     own := namfile^;
  832. end;
  833.  
  834.  
  835.  
  836. procedure getnam;
  837. var
  838.     err: integer;
  839.  
  840. begin
  841.     namfile^.validate := 0;
  842.     err := 0;
  843.     find(namfile,1,error := continue);
  844.     while namfile^.validate <> 1 do begin
  845.         deadcheck(err,'getnam');
  846.         collision_wait;
  847.         find(namfile,1,error := continue);
  848.     end;
  849.     nam := namfile^;
  850. end;
  851.  
  852. procedure freenam;
  853.  
  854. begin
  855.     unlock(namfile);
  856. end;
  857.  
  858. procedure freeown;
  859.  
  860. begin
  861.     unlock(namfile);
  862. end;
  863.  
  864. procedure putnam;
  865.  
  866. begin
  867.     locate(namfile,1);
  868.     namfile^:= nam;
  869.     put(namfile);
  870. end;
  871.  
  872. procedure putown;
  873.  
  874. begin
  875.     locate(namfile,2);
  876.     namfile^:= own;
  877.     put(namfile);
  878. end;
  879.  
  880.  
  881. procedure getobj(n: integer);
  882. var
  883.     err: integer;
  884.  
  885. begin
  886.     if n = 0 then
  887.         n := location;
  888.     objfile^.objnum := 0;
  889.     err := 0;
  890.     find(objfile,n,error := continue);
  891.     while objfile^.objnum <> n do begin
  892.         deadcheck(err,'getobj');
  893.         collision_wait;
  894.         find(objfile,n,error := continue);
  895.     end;
  896.     obj := objfile^;
  897. end;
  898.  
  899. procedure putobj;
  900.  
  901. begin
  902.     locate(objfile,obj.objnum);
  903.     objfile^ := obj;
  904.     put(objfile);
  905. end;
  906.  
  907. procedure freeobj;    { unlock the record if you're not going to write it }
  908.  
  909. begin
  910.     unlock(objfile);
  911. end;
  912.  
  913.  
  914.  
  915. procedure getint(n: integer);
  916. var
  917.     err: integer;
  918.  
  919. begin
  920.     intfile^.intnum := 0;
  921.     err := 0;
  922.     find(intfile,n,error := continue);
  923.     while intfile^.intnum <> n do begin
  924.         deadcheck(err,'getint');
  925.         collision_wait;
  926.         find(intfile,n,error := continue);
  927.     end;
  928.     anint := intfile^;
  929. end;
  930.  
  931.  
  932. procedure freeint;
  933.  
  934. begin
  935.     unlock(intfile);
  936. end;
  937.  
  938. procedure putint;
  939. var
  940.     n: integer;
  941.  
  942. begin
  943.     n := anint.intnum;
  944.     locate(intfile,n);
  945.     intfile^:= anint;
  946.     put(intfile);
  947. end;
  948.  
  949.  
  950.  
  951. procedure getspell(n: integer := 0);
  952. var
  953.     err: integer;
  954.  
  955. begin
  956.     if n = 0 then
  957.         n := mylog;
  958.  
  959.     spellfile^.recnum := 0;
  960.     err := 0;
  961.     find(spellfile,n,error := continue);
  962.     while spellfile^.recnum <> n do begin
  963.         deadcheck(err,'getspell');
  964.         collision_wait;
  965.         find(spellfile,n,error := continue);
  966.     end;
  967.     spell := spellfile^;
  968. end;
  969.  
  970.  
  971. procedure freespell;
  972.  
  973. begin
  974.     unlock(spellfile);
  975. end;
  976.  
  977. procedure putspell;
  978. var
  979.     n: integer;
  980.  
  981. begin
  982.     n := spell.recnum;
  983.     locate(spellfile,n);
  984.     spellfile^:= spell;
  985.     put(spellfile);
  986. end;
  987.  
  988.  
  989.  
  990. procedure getuser;    { get log rec with everyone's userids in it }
  991. var
  992.     err: integer;
  993.  
  994. begin
  995.     namfile^.validate := 0;
  996.     err := 0;
  997.     find(namfile,4,error := continue);
  998.     while namfile^.validate <> 4 do begin
  999.         deadcheck(err,'getuser');
  1000.         collision_wait;
  1001.         find(namfile,4,error := continue);
  1002.     end;
  1003.     user := namfile^;
  1004. end;
  1005.  
  1006. procedure freeuser;
  1007.  
  1008. begin
  1009.     unlock(namfile);
  1010. end;
  1011.  
  1012. procedure putuser;
  1013.  
  1014. begin
  1015.     locate(namfile,4);
  1016.     namfile^:= user;
  1017.     put(namfile);
  1018. end;
  1019.  
  1020.  
  1021.  
  1022. procedure getdate;    { get log rec with date of last play in it }
  1023. var
  1024.     err: integer;
  1025.  
  1026. begin
  1027.     namfile^.validate := 0;
  1028.     err := 0;
  1029.     find(namfile,7,error := continue);
  1030.     while namfile^.validate <> 7 do begin
  1031.         deadcheck(err,'getdate');
  1032.         collision_wait;
  1033.         find(namfile,7,error := continue);
  1034.     end;
  1035.     adate := namfile^;
  1036. end;
  1037.  
  1038. procedure freedate;
  1039.  
  1040. begin
  1041.     unlock(namfile);
  1042. end;
  1043.  
  1044. procedure putdate;
  1045.  
  1046. begin
  1047.     locate(namfile,7);
  1048.     namfile^:= adate;
  1049.     put(namfile);
  1050. end;
  1051.  
  1052.  
  1053. procedure gettime;    { get log rec with time of last play in it }
  1054. var
  1055.     err: integer;
  1056.  
  1057. begin
  1058.     namfile^.validate := 0;
  1059.     err := 0;
  1060.     find(namfile,8,error := continue);
  1061.     while namfile^.validate <> 8 do begin
  1062.         deadcheck(err,'gettime');
  1063.         collision_wait;
  1064.         find(namfile,8,error := continue);
  1065.     end;
  1066.     atime := namfile^;
  1067. end;
  1068.  
  1069. procedure freetime;
  1070.  
  1071. begin
  1072.     unlock(namfile);
  1073. end;
  1074.  
  1075. procedure puttime;
  1076.  
  1077. begin
  1078.     locate(namfile,8);
  1079.     namfile^:= atime;
  1080.     put(namfile);
  1081. end;
  1082.  
  1083.  
  1084.  
  1085. procedure getobjnam;
  1086. var
  1087.     err: integer;
  1088.  
  1089. begin
  1090.     namfile^.validate := 0;
  1091.     err := 0;
  1092.     find(namfile,5,error := continue);
  1093.     while namfile^.validate <> 5 do begin
  1094.         deadcheck(err,'getobjnam');
  1095.         collision_wait;
  1096.         find(namfile,5,error := continue);
  1097.     end;
  1098.     objnam := namfile^;
  1099. end;
  1100.  
  1101. procedure freeobjnam;
  1102.  
  1103. begin
  1104.     unlock(namfile);
  1105. end;
  1106.  
  1107. procedure putobjnam;
  1108.  
  1109. begin
  1110.     locate(namfile,5);
  1111.     namfile^:= objnam;
  1112.     put(namfile);
  1113. end;
  1114.  
  1115.  
  1116.  
  1117. procedure getobjown;
  1118. var
  1119.     err: integer;
  1120.  
  1121. begin
  1122.     namfile^.validate := 0;
  1123.     err := 0;
  1124.     find(namfile,6,error := continue);
  1125.     while namfile^.validate <> 6 do begin
  1126.         deadcheck(err,'getobjown');
  1127.         collision_wait;
  1128.         find(namfile,6,error := continue);
  1129.     end;
  1130.     objown := namfile^;
  1131. end;
  1132.  
  1133. procedure freeobjown;
  1134.  
  1135. begin
  1136.     unlock(namfile);
  1137. end;
  1138.  
  1139. procedure putobjown;
  1140.  
  1141. begin
  1142.     locate(namfile,6);
  1143.     namfile^:= objown;
  1144.     put(namfile);
  1145. end;
  1146.  
  1147.  
  1148.  
  1149. procedure getpers;    { get log rec with everyone's pers names in it }
  1150. var
  1151.     err: integer;
  1152.  
  1153. begin
  1154.     namfile^.validate := 0;
  1155.     err := 0;
  1156.     find(namfile,3,error := continue);
  1157.     while namfile^.validate <> 3 do begin
  1158.         deadcheck(err,'getpers');
  1159.         collision_wait;
  1160.         find(namfile,3,error := continue);
  1161.     end;
  1162.     pers := namfile^;
  1163. end;
  1164.  
  1165. procedure freepers;
  1166.  
  1167. begin
  1168.     unlock(namfile);
  1169. end;
  1170.  
  1171. procedure putpers;
  1172.  
  1173. begin
  1174.     locate(namfile,3);
  1175.     namfile^:= pers;
  1176.     put(namfile);
  1177. end;
  1178.  
  1179.  
  1180.  
  1181.  
  1182. procedure getevent(n: integer := 0);
  1183. var
  1184.     err: integer;
  1185.  
  1186. begin
  1187.     if n = 0 then
  1188.         n := location;
  1189.  
  1190.     n := (n mod numevnts) + 1;
  1191.  
  1192.     eventfile^.validat := 0;
  1193.     err := 0;
  1194.     find(eventfile,n,error := continue);
  1195.     while eventfile^.validat <> n do begin
  1196.         deadcheck(err,'getevent');
  1197.         collision_wait;
  1198.         find(eventfile,n,error := continue);
  1199.     end;
  1200.     event := eventfile^;
  1201. end;
  1202.  
  1203. procedure freeevent;
  1204.  
  1205. begin
  1206.     unlock(eventfile);
  1207. end;
  1208.  
  1209. procedure putevent;
  1210.  
  1211. begin
  1212.     locate(eventfile,event.validat);
  1213.     eventfile^:= event;
  1214.     put(eventfile);
  1215. end;
  1216.  
  1217.  
  1218. procedure getblock(n: integer);
  1219. var
  1220.     err: integer;
  1221.  
  1222. begin
  1223.     if debug then
  1224.         writeln('%getblock: ',n:1);
  1225.     descfile^.descrinum := 0;
  1226.     err := 0;
  1227.     find(descfile,n,error := continue);
  1228.     while descfile^.descrinum <> n do begin
  1229.         deadcheck(err,'getblock');
  1230.         collision_wait;
  1231.         find(descfile,n,error := continue);
  1232.     end;
  1233.     block := descfile^;
  1234. end;
  1235.  
  1236. procedure putblock;
  1237. var
  1238.     n: integer;
  1239.  
  1240. begin
  1241.     n := block.descrinum;
  1242.     if debug then
  1243.         writeln('%putblock: ',n:1);
  1244.     if n <> 0 then begin
  1245.         locate(descfile,n);
  1246.         descfile^ := block;
  1247.         put(descfile);
  1248.     end;
  1249. end;
  1250.  
  1251. procedure freeblock;    { unlock the record if you're not going to write it }
  1252.  
  1253. begin
  1254.     unlock(descfile);
  1255. end;
  1256.  
  1257.  
  1258.  
  1259.  
  1260.  
  1261. { *** new code begins here *** }
  1262.  
  1263.  
  1264. procedure getline(n: integer);
  1265. var
  1266.     err: integer;
  1267.  
  1268. begin
  1269.     if n = -1 then begin
  1270.         oneliner.theline := '';
  1271.     end else begin
  1272.         err := 0;
  1273.         linefile^.linenum := 0;
  1274.         find(linefile,n,error := continue);
  1275.         while linefile^.linenum <> n do begin
  1276.             deadcheck(err,'getline');
  1277.             collision_wait;
  1278.             find(linefile,n,error := continue);
  1279.         end;
  1280.         oneliner := linefile^;
  1281.     end;
  1282. end;
  1283.  
  1284. procedure putline;
  1285.  
  1286. begin
  1287.     if oneliner.linenum > 0 then begin
  1288.         locate(linefile,oneliner.linenum);
  1289.         linefile^ := oneliner;
  1290.         put(linefile);
  1291.     end;
  1292. end;
  1293.  
  1294. procedure freeline;    { unlock the record if you're not going to write it }
  1295.  
  1296. begin
  1297.     unlock(linefile);
  1298. end;
  1299.  
  1300.  
  1301.  
  1302.  
  1303. {
  1304. Index record 1 -- Description blocks that are free
  1305. Index record 2 -- One liners that are free
  1306. }
  1307.  
  1308.  
  1309. procedure getindex(n: integer);
  1310. var
  1311.     err: integer;
  1312.  
  1313. begin
  1314.     indexfile^.indexnum := 0;
  1315.     err := 0;
  1316.     find(indexfile,n,error := continue);
  1317.     while indexfile^.indexnum <> n do begin
  1318.         deadcheck(err,'getindex');
  1319.         collision_wait;
  1320.         find(indexfile,n,error := continue);
  1321.     end;
  1322.     indx := indexfile^;
  1323. end;
  1324.  
  1325. procedure putindex;
  1326.  
  1327. begin
  1328.     locate(indexfile,indx.indexnum);
  1329.     indexfile^ := indx;
  1330.     put(indexfile);
  1331. end;
  1332.  
  1333. procedure freeindex;    { unlock the record if you're not going to write it }
  1334.  
  1335. begin
  1336.     unlock(indexfile);
  1337. end;
  1338.  
  1339.  
  1340.  
  1341. {
  1342. First procedure of form alloc_X
  1343. Allocates the oneliner resource using the indexrec bitmaps
  1344.  
  1345. Return the number of a one liner if one is available
  1346. and remove it from the free list
  1347. }
  1348. function alloc_line(var n: integer):boolean;
  1349. var
  1350.     found: boolean;
  1351.  
  1352. begin
  1353.     getindex(I_LINE);
  1354.     if indx.inuse = indx.top then begin
  1355.         freeindex;
  1356.         n := 0;
  1357.         alloc_line := false;
  1358.         writeln('There are no available one line descriptions.');
  1359.     end else begin
  1360.         n := 1;
  1361.         found := false;
  1362.         while (not found) and (n <= indx.top) do begin
  1363.             if indx.free[n] then
  1364.                 found := true
  1365.             else
  1366.                 n := n + 1;
  1367.         end;
  1368.         if found then begin
  1369.             indx.free[n] := false;
  1370.             alloc_line := true;
  1371.             indx.inuse := indx.inuse + 1;
  1372.             putindex;
  1373.         end else begin
  1374.             freeindex;
  1375.             writeln('%serious error in alloc_line; notify Monster Manager');
  1376.             
  1377.             alloc_line := false;
  1378.         end;
  1379.     end;
  1380. end;
  1381.  
  1382. {
  1383. put the line specified by n back on the free list
  1384. zeroes n also, for convenience
  1385. }
  1386. procedure delete_line(var n: integer);
  1387.  
  1388. begin
  1389.     if n = DEFAULT_LINE then
  1390.         n := 0
  1391.     else if n > 0 then begin
  1392.         getindex(I_LINE);
  1393.         indx.inuse := indx.inuse - 1;
  1394.         indx.free[n] := true;
  1395.         putindex;
  1396.     end;
  1397.     n := 0;
  1398. end;
  1399.  
  1400.  
  1401.  
  1402. function alloc_int(var n: integer):boolean;
  1403. var
  1404.     found: boolean;
  1405.  
  1406. begin
  1407.     getindex(I_INT);
  1408.     if indx.inuse = indx.top then begin
  1409.         freeindex;
  1410.         n := 0;
  1411.         alloc_int := false;
  1412.         writeln('There are no available integer records.');
  1413.     end else begin
  1414.         n := 1;
  1415.         found := false;
  1416.         while (not found) and (n <= indx.top) do begin
  1417.             if indx.free[n] then
  1418.                 found := true
  1419.             else
  1420.                 n := n + 1;
  1421.         end;
  1422.         if found then begin
  1423.             indx.free[n] := false;
  1424.             alloc_int := true;
  1425.             indx.inuse := indx.inuse + 1;
  1426.             putindex;
  1427.         end else begin
  1428.             freeindex;
  1429.             writeln('%serious error in alloc_int; notify Monster Manager');
  1430.             
  1431.             alloc_int := false;
  1432.         end;
  1433.     end;
  1434. end;
  1435.  
  1436.  
  1437. procedure delete_int(var n: integer);
  1438.  
  1439. begin
  1440.     if n > 0 then begin
  1441.         getindex(I_INT);
  1442.         indx.inuse := indx.inuse - 1;
  1443.         indx.free[n] := true;
  1444.         putindex;
  1445.     end;
  1446.     n := 0;
  1447. end;
  1448.  
  1449.  
  1450.  
  1451. {
  1452. Return the number of a description block if available and
  1453. remove it from the free list
  1454. }
  1455. function alloc_block(var n: integer):boolean;
  1456. var
  1457.     found: boolean;
  1458.  
  1459. begin
  1460.     if debug then
  1461.         writeln('%alloc_block entry');
  1462.     getindex(I_BLOCK);
  1463.     if indx.inuse = indx.top then begin
  1464.         freeindex;
  1465.         n := 0;
  1466.         alloc_block := false;
  1467.         writeln('There are no available description blocks.');
  1468.     end else begin
  1469.         n := 1;
  1470.         found := false;
  1471.         while (not found) and (n <= indx.top) do begin
  1472.             if indx.free[n] then
  1473.                 found := true
  1474.             else
  1475.                 n := n + 1;
  1476.         end;
  1477.         if found then begin
  1478.             indx.free[n] := false;
  1479.             alloc_block := true;
  1480.             indx.inuse := indx.inuse + 1;
  1481.             putindex;
  1482.             if debug then
  1483.                 writeln('%alloc_block successful');
  1484.         end else begin
  1485.             freeindex;
  1486.             writeln('%serious error in alloc_block; notify Monster Manager');
  1487.             alloc_block := false;
  1488.         end;
  1489.     end;
  1490. end;
  1491.  
  1492.  
  1493.  
  1494.  
  1495. {
  1496. puts a description block back on the free list
  1497. zeroes n for convenience
  1498. }
  1499. procedure delete_block(var n: integer);
  1500.  
  1501. begin
  1502.     if n = DEFAULT_LINE then
  1503.         n := 0        { no line really exists in the file }
  1504.     else if n > 0 then begin
  1505.         getindex(I_BLOCK);
  1506.         indx.inuse := indx.inuse - 1;
  1507.         indx.free[n] := true;
  1508.         putindex;
  1509.         n := 0;
  1510.     end else if n < 0 then begin
  1511.         n := (- n);
  1512.         delete_line(n);
  1513.     end;
  1514. end;
  1515.  
  1516.  
  1517.  
  1518. {
  1519. Return the number of a room if one is available
  1520. and remove it from the free list
  1521. }
  1522. function alloc_room(var n: integer):boolean;
  1523. var
  1524.     found: boolean;
  1525.  
  1526. begin
  1527.     getindex(I_ROOM);
  1528.     if indx.inuse = indx.top then begin
  1529.         freeindex;
  1530.         n := 0;
  1531.         alloc_room := false;
  1532.         writeln('There are no available free rooms.');
  1533.     end else begin
  1534.         n := 1;
  1535.         found := false;
  1536.         while (not found) and (n <= indx.top) do begin
  1537.             if indx.free[n] then
  1538.                 found := true
  1539.             else
  1540.                 n := n + 1;
  1541.         end;
  1542.         if found then begin
  1543.             indx.free[n] := false;
  1544.             alloc_room := true;
  1545.             indx.inuse := indx.inuse + 1;
  1546.             putindex;
  1547.         end else begin
  1548.             freeindex;
  1549.             writeln('%serious error in alloc_room; notify Monster Manager');
  1550.             alloc_room := false;
  1551.         end;
  1552.     end;
  1553. end;
  1554.  
  1555. {
  1556. Called by DEL_ROOM()
  1557. put the room specified by n back on the free list
  1558. zeroes n also, for convenience
  1559. }
  1560. procedure delete_room(var n: integer);
  1561.  
  1562. begin
  1563.     if n <> 0 then begin
  1564.         getindex(I_ROOM);
  1565.         indx.inuse := indx.inuse - 1;
  1566.         indx.free[n] := true;
  1567.         putindex;
  1568.         n := 0;
  1569.     end;
  1570. end;
  1571.  
  1572.  
  1573.  
  1574. function alloc_log(var n: integer):boolean;
  1575. var
  1576.     found: boolean;
  1577.  
  1578. begin
  1579.     getindex(I_PLAYER);
  1580.     if indx.inuse = indx.top then begin
  1581.         freeindex;
  1582.         n := 0;
  1583.         alloc_log := false;
  1584.         writeln('There are too many monster players, you can''t find a space.');
  1585.     end else begin
  1586.         n := 1;
  1587.         found := false;
  1588.         while (not found) and (n <= indx.top) do begin
  1589.             if indx.free[n] then
  1590.                 found := true
  1591.             else
  1592.                 n := n + 1;
  1593.         end;
  1594.         if found then begin
  1595.             indx.free[n] := false;
  1596.             alloc_log := true;
  1597.             indx.inuse := indx.inuse + 1;
  1598.             putindex;
  1599.         end else begin
  1600.             freeindex;
  1601.             writeln('%serious error in alloc_log; notify Monster Manager');
  1602.             alloc_log := false;
  1603.         end;
  1604.     end;
  1605. end;
  1606.  
  1607. procedure delete_log(var n: integer);
  1608.  
  1609. begin
  1610.     if n <> 0 then begin
  1611.         getindex(I_PLAYER);
  1612.         indx.inuse := indx.inuse - 1;
  1613.         indx.free[n] := true;
  1614.         putindex;
  1615.         n := 0;
  1616.     end;
  1617. end;
  1618.  
  1619.  
  1620. function lowcase(s: string):string;
  1621. var
  1622.     sprime: string;
  1623.     i: integer;
  1624.  
  1625. begin
  1626.     if length(s) = 0 then
  1627.         lowcase := ''
  1628.     else begin
  1629.         sprime := s;
  1630.         for i := 1 to length(s) do
  1631.             if sprime[i] in ['A'..'Z'] then
  1632.                sprime[i] := chr(ord('a')+(ord(sprime[i])-ord('A')));
  1633.         lowcase := sprime;
  1634.     end;
  1635. end;
  1636.  
  1637.  
  1638. { lookup a spell with disambiguation in the spell list }
  1639.  
  1640. function lookup_spell(var n: integer;s:string): boolean;
  1641. var
  1642.     i,poss,maybe,num: integer;
  1643.  
  1644. begin
  1645.     s := lowcase(s);
  1646.     i := 1;
  1647.     maybe := 0;
  1648.     num := 0;
  1649.     for i := 1 to numspells do begin
  1650.         if s = spells[i] then
  1651.             num := i
  1652.         else if index(spells[i],s) = 1 then begin
  1653.             maybe := maybe + 1;
  1654.             poss := i;
  1655.         end;
  1656.     end;
  1657.     if num <> 0 then begin
  1658.         n := num;
  1659.         lookup_spell := true;
  1660.     end else if maybe = 1 then begin
  1661.         n := poss;
  1662.         lookup_spell := true;
  1663.     end else if maybe > 1 then begin
  1664.         lookup_spell := false;
  1665.     end else begin
  1666.         lookup_spell := false;
  1667.     end;
  1668. end;
  1669.  
  1670.  
  1671. function lookup_user(var pnum: integer;s: string): boolean;
  1672. var
  1673.     i,poss,maybe,num: integer;
  1674.  
  1675. begin
  1676.     getuser;
  1677.     freeuser;
  1678.     getindex(I_PLAYER);
  1679.     freeindex;
  1680.  
  1681.     s := lowcase(s);
  1682.     i := 1;
  1683.     maybe := 0;
  1684.     num := 0;
  1685.     for i := 1 to indx.top do begin
  1686.         if not(indx.free[i]) then begin
  1687.             if s = user.idents[i] then
  1688.                 num := i
  1689.             else if index(user.idents[i],s) = 1 then begin
  1690.                 maybe := maybe + 1;
  1691.                 poss := i;
  1692.             end;
  1693.         end;
  1694.     end;
  1695.     if num <> 0 then begin
  1696.         pnum := num;
  1697.         lookup_user := true;
  1698.     end else if maybe = 1 then begin
  1699.         pnum := poss;
  1700.         lookup_user := true;
  1701.     end else if maybe > 1 then begin
  1702. {        writeln('-- Ambiguous direction');    }
  1703.         lookup_user := false;
  1704.     end else begin
  1705.         lookup_user := false;
  1706. {        writeln('-- Unknown direction');    }
  1707.     end;
  1708. end;
  1709.  
  1710.  
  1711. function alloc_obj(var n: integer):boolean;
  1712. var
  1713.     found: boolean;
  1714.  
  1715. begin
  1716.     getindex(I_OBJECT);
  1717.     if indx.inuse = indx.top then begin
  1718.         freeindex;
  1719.         n := 0;
  1720.         alloc_obj := false;
  1721.         writeln('All of the possible objects have been made.');
  1722.     end else begin
  1723.         n := 1;
  1724.         found := false;
  1725.         while (not found) and (n <= indx.top) do begin
  1726.             if indx.free[n] then
  1727.                 found := true
  1728.             else
  1729.                 n := n + 1;
  1730.         end;
  1731.         if found then begin
  1732.             indx.free[n] := false;
  1733.             alloc_obj := true;
  1734.             indx.inuse := indx.inuse + 1;
  1735.             putindex;
  1736.         end else begin
  1737.             freeindex;
  1738.             writeln('%serious error in alloc_obj; notify Monster Manager');
  1739.             alloc_obj := false;
  1740.         end;
  1741.     end;
  1742. end;
  1743.  
  1744.  
  1745. procedure delete_obj(var n: integer);
  1746.  
  1747. begin
  1748.     if n <> 0 then begin
  1749.         getindex(I_OBJECT);
  1750.         indx.inuse := indx.inuse - 1;
  1751.         indx.free[n] := true;
  1752.         putindex;
  1753.         n := 0;
  1754.     end;
  1755. end;
  1756.  
  1757.  
  1758.  
  1759.  
  1760. function lookup_obj(var pnum: integer;s: string): boolean;
  1761. var
  1762.     i,poss,maybe,num: integer;
  1763.     tmp: string;
  1764.  
  1765. begin
  1766.     getobjnam;
  1767.     freeobjnam;
  1768.     getindex(I_OBJECT);
  1769.     freeindex;
  1770.  
  1771.     s := lowcase(s);
  1772.     i := 1;
  1773.     maybe := 0;
  1774.     num := 0;
  1775.     for i := 1 to indx.top do begin
  1776.         if not(indx.free[i]) then begin
  1777.             if s = objnam.idents[i] then
  1778.                 num := i
  1779.             else if index(objnam.idents[i],s) = 1 then begin
  1780.                 maybe := maybe + 1;
  1781.                 poss := i;
  1782.             end;
  1783.         end;
  1784.     end;
  1785.     if num <> 0 then begin
  1786.         pnum := num;
  1787.         lookup_obj := true;
  1788.     end else if maybe = 1 then begin
  1789.         pnum := poss;
  1790.         lookup_obj := true;
  1791.     end else if maybe > 1 then begin
  1792. {        writeln('-- Ambiguous direction');    }
  1793.         lookup_obj := false;
  1794.     end else begin
  1795.         lookup_obj := false;
  1796. {        writeln('-- Unknown direction');    }
  1797.     end;
  1798. end;
  1799.  
  1800.  
  1801.  
  1802. { returns true if object N is in this room }
  1803.  
  1804. function obj_here(n: integer): boolean;
  1805. var
  1806.     i: integer;
  1807.     found: boolean;
  1808.  
  1809. begin
  1810.     i := 1;
  1811.     found := false;
  1812.     while (i <= maxobjs) and (not found) do begin
  1813.         if here.objs[i] = n then
  1814.             found := true
  1815.         else
  1816.             i := i + 1;
  1817.     end;
  1818.     obj_here := found;
  1819. end;
  1820.  
  1821.  
  1822.  
  1823.  
  1824. { returns true if object N is being held by the player }
  1825.  
  1826. function obj_hold(n: integer): boolean;
  1827. var
  1828.     i: integer;
  1829.     found: boolean;
  1830.  
  1831. begin
  1832.     if n = 0 then
  1833.         obj_hold := false
  1834.     else begin
  1835.         i := 1;
  1836.         found := false;
  1837.         while (i <= maxhold) and (not found) do begin
  1838.             if here.people[myslot].holding[i] = n then
  1839.                 found := true
  1840.             else
  1841.                 i := i + 1;
  1842.         end;
  1843.         obj_hold := found;
  1844.     end;
  1845. end;
  1846.  
  1847.  
  1848.  
  1849. { return the slot of an object that is HERE }
  1850. function find_obj(objnum: integer): integer;
  1851. var
  1852.     i: integer;
  1853.  
  1854. begin
  1855.     i := 1;
  1856.     find_obj := 0;
  1857.     while i <= maxobjs do begin
  1858.         if here.objs[i] = objnum then
  1859.             find_obj := i;
  1860.         i := i + 1;
  1861.     end;
  1862. end;
  1863.  
  1864.  
  1865.  
  1866. { similar to lookup_obj, but only returns true if the object is in
  1867.   this room or is being held by the player }
  1868.  
  1869. function parse_obj(var n: integer; s: string;override: boolean := false): boolean;
  1870. var
  1871.     slot: integer;
  1872.  
  1873. begin
  1874.     if lookup_obj(n,s) then begin
  1875.         if obj_here(n) or obj_hold(n) then
  1876.  
  1877.             { took out a great block of code that wouldn't let
  1878.               parse_obj work if player couldn't see object }
  1879.  
  1880.             parse_obj := true;
  1881.     end else
  1882.         parse_obj := false;
  1883. end;
  1884.  
  1885.  
  1886.  
  1887.  
  1888. function lookup_pers(var pnum: integer;s: string): boolean;
  1889. var
  1890.     i,poss,maybe,num: integer;
  1891.     pname: string;
  1892.  
  1893. begin
  1894.     getpers;
  1895.     freepers;
  1896.     getindex(I_PLAYER);
  1897.     freeindex;
  1898.  
  1899.     s := lowcase(s);
  1900.     i := 1;
  1901.     maybe := 0;
  1902.     num := 0;
  1903.     for i := 1 to indx.top do begin
  1904.         if not(indx.free[i]) then begin
  1905.             pname := lowcase(pers.idents[i]);
  1906.  
  1907.             if s = pname then
  1908.                 num := i
  1909.             else if index(pname,s) = 1 then begin
  1910.                 maybe := maybe + 1;
  1911.                 poss := i;
  1912.             end;
  1913.         end;
  1914.     end;
  1915.     if num <> 0 then begin
  1916.         pnum := num;
  1917.         lookup_pers := true;
  1918.     end else if maybe = 1 then begin
  1919.         pnum := poss;
  1920.         lookup_pers := true;
  1921.     end else if maybe > 1 then begin
  1922. {        writeln('-- Ambiguous direction');    }
  1923.         lookup_pers := false;
  1924.     end else begin
  1925.         lookup_pers := false;
  1926. {        writeln('-- Unknown direction');    }
  1927.     end;
  1928. end;
  1929.  
  1930.  
  1931.  
  1932. function parse_pers(var pnum: integer;s: string): boolean;
  1933. var
  1934.     persnum: integer;
  1935.     i,poss,maybe,num: integer;
  1936.     pname: string;
  1937.  
  1938. begin
  1939.     gethere;
  1940.     s := lowcase(s);
  1941.     i := 1;
  1942.     maybe := 0;
  1943.     num := 0;
  1944.     for i := 1 to maxpeople do begin
  1945. {        if here.people[i].username <> '' then begin    }
  1946.  
  1947.         if here.people[i].kind > 0 then begin
  1948.             pname := lowcase(here.people[i].name);
  1949.  
  1950.             if s = pname then
  1951.                 num := i
  1952.             else if index(pname,s) = 1 then begin
  1953.                 maybe := maybe + 1;
  1954.                 poss := i;
  1955.             end;
  1956.         end;
  1957.     end;
  1958.     if num <> 0 then begin
  1959.         persnum := num;
  1960.         parse_pers := true;
  1961.     end else if maybe = 1 then begin
  1962.         persnum := poss;
  1963.         parse_pers := true;
  1964.     end else if maybe > 1 then begin
  1965.         persnum := 0;
  1966.         parse_pers := false;
  1967.     end else begin
  1968.         persnum := 0;
  1969.         parse_pers := false;
  1970.     end;
  1971.     if persnum > 0 then begin
  1972.         if here.people[persnum].hiding > 0 then
  1973.             parse_pers := false
  1974.         else begin
  1975.             parse_pers := true;
  1976.             pnum := persnum;
  1977.         end;
  1978.     end;
  1979. end;
  1980.  
  1981.  
  1982.  
  1983.  
  1984.  
  1985. {
  1986. Returns TRUE if player is owner of room n
  1987. If no n is given default will be this room (location)
  1988. }
  1989. function is_owner(n: integer := 0;surpress:boolean := false): boolean;
  1990.  
  1991. begin
  1992.     gethere(n);
  1993.     if (here.owner = userid) or (privd) then
  1994.         is_owner := true
  1995.     else begin
  1996.         is_owner := false;
  1997.         if not(surpress) then
  1998.             writeln('You are not the owner of this room.');
  1999.     end;
  2000. end;
  2001.  
  2002.  
  2003. function room_owner(n: integer): string;
  2004.  
  2005. begin
  2006.     if n <> 0 then begin
  2007.         gethere(n);
  2008.         room_owner := here.owner;
  2009.         gethere;    { restore old state! }
  2010.     end else
  2011.         room_owner := 'no room';
  2012. end;
  2013.  
  2014. {
  2015. Returns TRUE if player is allowed to alter the exit
  2016. TRUE if either this room or if target room is owned by player
  2017. }
  2018.  
  2019. function can_alter(dir: integer;room: integer := 0): boolean;
  2020.  
  2021. begin
  2022.     gethere;
  2023.     if (here.owner=userid) or (privd) then begin
  2024.         can_alter := true
  2025.     end else begin
  2026.         if here.exits[dir].toloc > 0 then begin
  2027.             if room_owner(here.exits[dir].toloc) = userid then
  2028.                 can_alter := true
  2029.             else
  2030.                 can_alter := false;
  2031.         end else
  2032.             can_alter := false;
  2033.     end;
  2034. end;
  2035.  
  2036. function can_make(dir: integer;room: integer := 0): boolean;
  2037.  
  2038. begin
  2039.     gethere(room);    { 5 is accept door }
  2040.     if (here.exits[dir].toloc <> 0) then begin
  2041.         writeln('There is already an exit there.  Use UNLINK or RELINK.');
  2042.         can_make := false;
  2043.     end else begin
  2044.         if (here.owner = userid) or        { I'm the owner }
  2045.            (here.exits[dir].kind = 5) or    { there's an accept }
  2046.            (privd) or        { Monster Manager }
  2047.            (here.owner = '*')            { disowned room }
  2048.                              then
  2049.             can_make := true
  2050.         else begin
  2051.             can_make := false;
  2052.             writeln('You are not allowed to create an exit there.');
  2053.         end;
  2054.     end;
  2055. end;
  2056.  
  2057.  
  2058. {
  2059. print a one liner
  2060. }
  2061. procedure print_line(n: integer);
  2062.  
  2063. begin
  2064.     if n = DEFAULT_LINE then
  2065.         writeln('<default line>')
  2066.     else if n > 0 then begin
  2067.         getline(n);
  2068.         freeline;
  2069.         writeln(oneliner.theline);
  2070.     end;
  2071. end;
  2072.  
  2073.  
  2074.  
  2075. procedure print_desc(dsc: integer;default:string := '<no default supplied>');
  2076. var
  2077.     i: integer;
  2078.  
  2079. begin
  2080.     if dsc = DEFAULT_LINE then begin
  2081.         writeln(default);
  2082.     end else if dsc > 0 then begin
  2083.         getblock(dsc);
  2084.         freeblock;
  2085.         i := 1;
  2086.         while i <= block.desclen do begin
  2087.             writeln(block.lines[i]);
  2088.             i := i + 1;
  2089.         end;
  2090.     end else if dsc < 0 then begin
  2091.         print_line(abs(dsc));
  2092.     end;
  2093. end;
  2094.  
  2095.  
  2096.  
  2097.  
  2098. procedure make_line(var n: integer;prompt : string := '';limit:integer := 79);
  2099. var
  2100.     s: string;
  2101.     ok: boolean;
  2102.  
  2103. begin
  2104.     writeln('Type ** to leave line unchanged, * to make [no line]');
  2105.     grab_line(prompt,s);
  2106.     if s = '**' then begin
  2107.         writeln('No changes.');
  2108.     end else if s = '***' then begin
  2109.         n := DEFAULT_LINE;
  2110.     end else if s = '*' then begin
  2111.         if debug then
  2112.             writeln('%deleting line ',n:1);
  2113.         delete_line(n);
  2114.     end else if s = '' then begin
  2115.         if debug then
  2116.             writeln('%deleting line ',n:1);
  2117.         delete_line(n);
  2118.     end else if length(s) > limit then begin
  2119.         writeln('Please limit your string to ',limit:1,' characters.');
  2120.     end else begin
  2121.         if (n = 0) or (n = DEFAULT_LINE) then begin
  2122.             if debug then
  2123.                 writeln('%makeline: allocating line');
  2124.             ok := alloc_line(n);
  2125.         end else
  2126.             ok := true;
  2127.  
  2128.         if ok then begin
  2129.             if debug then
  2130.                 writeln('%ok in makeline');
  2131.             getline(n);
  2132.             oneliner.theline := s;
  2133.             putline;
  2134.  
  2135.             if debug then
  2136.                 writeln('%completed putline in makeline');
  2137.         end;
  2138.     end;
  2139. end;
  2140.  
  2141.  
  2142. { translate a direction s [north, south, etc...] into the integer code }
  2143.  
  2144. function lookup_dir(var dir: integer;s:string): boolean;
  2145. var
  2146.     i,poss,maybe,num: integer;
  2147.  
  2148. begin
  2149.     s := lowcase(s);
  2150.     i := 1;
  2151.     maybe := 0;
  2152.     num := 0;
  2153.     for i := 1 to maxexit do begin
  2154.         if s = direct[i] then
  2155.             num := i
  2156.         else if index(direct[i],s) = 1 then begin
  2157.             maybe := maybe + 1;
  2158.             poss := i;
  2159.         end;
  2160.     end;
  2161.     if num <> 0 then begin
  2162.         dir := num;
  2163.         lookup_dir := true;
  2164.     end else if maybe = 1 then begin
  2165.         dir := poss;
  2166.         lookup_dir := true;
  2167.     end else if maybe > 1 then begin
  2168.         lookup_dir := false;
  2169. {        writeln('-- Ambiguous direction');    }
  2170.     end else begin
  2171.         lookup_dir := false;
  2172. {        writeln('-- Unknown direction');    }
  2173.     end;
  2174. end;
  2175.  
  2176.  
  2177. function lookup_show(var n: integer;s:string): boolean;
  2178. var
  2179.     i,poss,maybe,num: integer;
  2180.  
  2181. begin
  2182.     s := lowcase(s);
  2183.     i := 1;
  2184.     maybe := 0;
  2185.     num := 0;
  2186.     for i := 1 to numshow do begin
  2187.         if s = show[i] then
  2188.             num := i
  2189.         else if index(show[i],s) = 1 then begin
  2190.             maybe := maybe + 1;
  2191.             poss := i;
  2192.         end;
  2193.     end;
  2194.     if num <> 0 then begin
  2195.         n := num;
  2196.         lookup_show := true;
  2197.     end else if maybe = 1 then begin
  2198.         n := poss;
  2199.         lookup_show := true;
  2200.     end else if maybe > 1 then begin
  2201.         lookup_show := false;
  2202. {        writeln('-- Ambiguous direction');    }
  2203.     end else begin
  2204.         lookup_show := false;
  2205. {        writeln('-- Unknown direction');    }
  2206.     end;
  2207. end;
  2208.  
  2209. function lookup_set(var n: integer;s:string): boolean;
  2210. var
  2211.     i,poss,maybe,num: integer;
  2212.  
  2213. begin
  2214.     s := lowcase(s);
  2215.     i := 1;
  2216.     maybe := 0;
  2217.     num := 0;
  2218.     for i := 1 to numset do begin
  2219.         if s = setkey[i] then
  2220.             num := i
  2221.         else if index(setkey[i],s) = 1 then begin
  2222.             maybe := maybe + 1;
  2223.             poss := i;
  2224.         end;
  2225.     end;
  2226.     if num <> 0 then begin
  2227.         n := num;
  2228.         lookup_set := true;
  2229.     end else if maybe = 1 then begin
  2230.         n := poss;
  2231.         lookup_set := true;
  2232.     end else if maybe > 1 then begin
  2233.         lookup_set := false;
  2234.     end else begin
  2235.         lookup_set := false;
  2236.     end;
  2237. end;
  2238.  
  2239.  
  2240. function lookup_room(var n: integer; s: string): boolean;
  2241. var
  2242.     found: boolean;
  2243.     top: integer;
  2244.  
  2245.     i,
  2246.     poss,
  2247.     maybe,
  2248.     num:    integer;
  2249.  
  2250. begin
  2251.     if s <> '' then begin
  2252.         s := lowcase(s);        { case insensitivity }
  2253.         getnam;
  2254.         freenam;
  2255.         getindex(I_ROOM);
  2256.         freeindex;
  2257.         top := indx.top;
  2258.  
  2259.  
  2260.         i := 1;
  2261.         maybe := 0;
  2262.         num := 0;
  2263.         for i := 1 to top do begin
  2264.             if s = nam.idents[i] then
  2265.                 num := i
  2266.             else if index(nam.idents[i],s) = 1 then begin
  2267.                 maybe := maybe + 1;
  2268.                 poss := i;
  2269.             end;
  2270.         end;
  2271.         if num <> 0 then begin
  2272.             lookup_room := true;
  2273.             n := num;
  2274.         end else if maybe = 1 then begin
  2275.             lookup_room := true;
  2276.             n := poss;
  2277.         end else if maybe > 1 then begin
  2278.             lookup_room := false;
  2279.         end else begin
  2280.             lookup_room := false;
  2281.         end;
  2282.  
  2283.     end else
  2284.         lookup_room := false;
  2285. end;
  2286.  
  2287.  
  2288. function exact_room(var n: integer;s: string): boolean;
  2289. var
  2290.     match: boolean;
  2291.  
  2292. begin
  2293.     if debug then
  2294.         writeln('%exact room: s = ',s);
  2295.     if lookup_room(n,s) then begin
  2296.         if nam.idents[n] = lowcase(s) then
  2297.             exact_room := true
  2298.         else
  2299.             exact_room := false;
  2300.     end else
  2301.         exact_room := false;
  2302. end;
  2303.  
  2304.  
  2305. function exact_pers(var n: integer;s: string): boolean;
  2306. var
  2307.     match: boolean;
  2308.  
  2309. begin
  2310.     if lookup_pers(n,s) then begin
  2311.         if lowcase(pers.idents[n]) = lowcase(s) then
  2312.             exact_pers := true
  2313.         else
  2314.             exact_pers := false;
  2315.     end else
  2316.         exact_pers := false;
  2317. end;
  2318.  
  2319.  
  2320. function exact_user(var n: integer;s: string): boolean;
  2321. var
  2322.     match: boolean;
  2323.  
  2324. begin
  2325.     if lookup_user(n,s) then begin
  2326.         if lowcase(user.idents[n]) = lowcase(s) then
  2327.             exact_user := true
  2328.         else
  2329.             exact_user := false;
  2330.     end else
  2331.         exact_user := false;
  2332. end;
  2333.  
  2334.  
  2335. function exact_obj(var n: integer;s: string): boolean;
  2336. var
  2337.     match: boolean;
  2338.  
  2339. begin
  2340.     if lookup_obj(n,s) then begin
  2341.         if objnam.idents[n] = lowcase(s) then
  2342.             exact_obj := true
  2343.         else
  2344.             exact_obj := false;
  2345.     end else
  2346.         exact_obj := false;
  2347. end;
  2348.  
  2349.  
  2350.  
  2351. {
  2352. Return n as the direction number if s is a valid alias for an exit
  2353. }
  2354. function lookup_alias(var n: integer; s: string): boolean;
  2355. var
  2356.     i,poss,maybe,num: integer;
  2357.  
  2358. begin
  2359.     gethere;
  2360.     s := lowcase(s);
  2361.     i := 1;
  2362.     maybe := 0;
  2363.     num := 0;
  2364.     for i := 1 to maxexit do begin
  2365.         if s = here.exits[i].alias then
  2366.             num := i
  2367.         else if index(here.exits[i].alias,s) = 1 then begin
  2368.             maybe := maybe + 1;
  2369.             poss := i;
  2370.         end;
  2371.     end;
  2372.     if num <> 0 then begin
  2373.         n := num;
  2374.         lookup_alias := true;
  2375.     end else if maybe = 1 then begin
  2376.         n := poss;
  2377.         lookup_alias := true;
  2378.     end else if maybe > 1 then begin
  2379.         lookup_alias := false;
  2380.     end else begin
  2381.         lookup_alias := false;
  2382.     end;
  2383. end;
  2384.  
  2385.  
  2386. procedure exit_default(dir, kind: integer);
  2387.  
  2388. begin
  2389.     case kind of
  2390.  
  2391.     1: writeln('There is a passage leading ',direct[dir],'.');
  2392.     2: writeln('There is a locked door leading ',direct[dir],'.');
  2393.     5:    case dir of
  2394.             north,south,east,west:
  2395.                 writeln('A note on the ',direct[dir],' wall says "Your exit here."');
  2396.             up: writeln('A note on the ceiling says "Your exit here."');
  2397.             down: writeln('A note on the floor says "Your exit here."');
  2398.         end;
  2399.     otherwise writeln('There is an exit: ',direct[dir]);
  2400.     end;
  2401. end;
  2402.  
  2403.  
  2404. {
  2405. Prints out the exits here for DO_LOOK()
  2406. }
  2407. procedure show_exits;
  2408. var
  2409.     i: integer;
  2410.     one: boolean;
  2411.     cansee: boolean;
  2412.  
  2413. begin
  2414.     one := false;
  2415.     for i := 1 to maxexit do begin
  2416.         if (here.exits[i].toloc <> 0) or { there is an exit }
  2417.            (here.exits[i].kind = 5) then begin { there could be an exit }
  2418.  
  2419.             if (here.exits[i].hidden = 0) or
  2420.                (found_exit[i]) then
  2421.                 cansee := true
  2422.             else
  2423.                 cansee := false;
  2424.  
  2425.             if here.exits[i].kind = 6 then begin
  2426.                 { door kind only visible with object }
  2427.                 if obj_hold( here.exits[i].objreq ) then
  2428.                     cansee := true
  2429.                 else
  2430.                     cansee := false;
  2431.             end;
  2432.  
  2433.             if cansee then begin
  2434.                 if here.exits[i].exitdesc = DEFAULT_LINE then begin
  2435.                     exit_default(i,here.exits[i].kind);
  2436.                     { give it direction and type }
  2437.                     one := true;
  2438.                 end else if here.exits[i].exitdesc > 0 then begin
  2439.                     print_line(here.exits[i].exitdesc);
  2440.                     one := true;
  2441.                 end;
  2442.             end;
  2443.         end;
  2444.     end;
  2445.     if one then
  2446.         writeln;
  2447. end;
  2448.  
  2449.  
  2450. procedure setevent;
  2451.  
  2452. begin
  2453.     getevent;
  2454.     freeevent;
  2455.     myevent := event.point;
  2456. end;
  2457.  
  2458.  
  2459.  
  2460. function isnum(s: string): boolean;
  2461. var
  2462.     i: integer;
  2463.  
  2464. begin
  2465.     isnum := true;
  2466.     if length(s) < 1 then
  2467.         isnum := false
  2468.     else begin
  2469.         i := 1;
  2470.         while i <= length(s) do begin
  2471.             if not (s[i] in ['0'..'9']) then
  2472.                 isnum := false;
  2473.             i := i + 1;
  2474.         end;
  2475.     end;
  2476. end;
  2477.  
  2478. function number(s: string): integer;
  2479. var
  2480.     i: integer;
  2481.  
  2482. begin
  2483.     if (length(s) < 1) or not(s[1] in ['0'..'9']) then
  2484.         number := 0
  2485.     else begin
  2486.         readv(s,i);
  2487.         number := i;
  2488.     end;
  2489. end;
  2490.  
  2491.  
  2492.  
  2493. procedure log_event(    send: integer := 0;    { slot of sender }
  2494.             act:integer;        { what event occurred }
  2495.             targ: integer := 0;    { target of event }
  2496.             p: integer := 0;    { expansion parameter }
  2497.             s: string := '';    { string for messages }
  2498.             room: integer := 0    { room to log event in }
  2499.            );
  2500.  
  2501. begin
  2502.     if room = 0 then
  2503.         room := location;
  2504.     getevent(room);
  2505.     event.point := event.point + 1;
  2506.     if debug then
  2507.         writeln('%logging event ',act:1,' to point ',event.point:1);
  2508.     if event.point > maxevent then
  2509.         event.point := 1;
  2510.     with event.evnt[event.point] do begin
  2511.         sender := send;
  2512.         action := act;
  2513.         target := targ;
  2514.         parm := p;
  2515.         msg := s;
  2516.         loc := room;
  2517.     end;
  2518.     putevent;
  2519. end;
  2520.  
  2521. procedure log_action(theaction,thetarget: integer);
  2522.  
  2523. begin
  2524.     if debug then
  2525.         writeln('%log_action(',theaction:1,',',thetarget:1,')');
  2526.     getroom;
  2527.     here.people[myslot].act := theaction;
  2528.     here.people[myslot].targ := thetarget;
  2529.     putroom;
  2530.  
  2531.     logged_act := true;
  2532.     log_event(myslot,E_ACTION,thetarget,theaction,myname);
  2533. end;
  2534.  
  2535.  
  2536. function desc_action(theaction,thetarget: integer): string;
  2537. var
  2538.     s: string;
  2539.  
  2540. begin
  2541.     case theaction of    { use command mnemonics }
  2542.         look:      s:= ' looking around the room.';
  2543.         form:      s:= ' creating a new room.';
  2544.         desc:      s:= ' editing the description to this room.';
  2545.         e_detail:  s := ' adding details to the room.';
  2546.         c_custom:  s := ' customizing an exit here.';
  2547.         e_custroom:s := ' customizing this room.';
  2548.         e_program: s := ' customizing an object.';
  2549.         c_self:       s := ' editing a self-description.';
  2550.         e_usecrystal: s := ' hunched over a crystal orb, immersed in its glow.';
  2551.         link:       s := ' creating an exit here.';
  2552.         c_system:  s := ' in system maintenance mode.';
  2553.  
  2554.         otherwise s := ' here.'
  2555.     end;
  2556.     desc_action := s;
  2557. end;
  2558.  
  2559.  
  2560. function protected(n: integer := 0): boolean;
  2561.  
  2562. begin
  2563.     if n = 0 then
  2564.         n := myslot;
  2565.     if here.people[n].act in [e_detail,c_custom,
  2566.                   e_custroom,e_program,
  2567.                   c_self,c_system] then
  2568.         protected := true
  2569.     else
  2570.         protected := false;
  2571. end;
  2572.  
  2573.  
  2574.  
  2575. {
  2576. user procedure to designate an exit for acceptance of links
  2577. }
  2578. procedure do_accept(s: string);
  2579. var
  2580.     dir: integer;
  2581.  
  2582. begin
  2583.     if lookup_dir(dir,s) then begin
  2584.         if can_make(dir) then begin
  2585.             getroom;
  2586.             here.exits[dir].kind := 5;
  2587.             putroom;
  2588.  
  2589.             log_event(myslot,E_ACCEPT,0,0);
  2590.             writeln('Someone will be able to make an exit ',direct[dir],'.');
  2591.         end;
  2592.     end else
  2593.         writeln('To allow others to make an exit, type ACCEPT <direction of exit>.');
  2594. end;
  2595.  
  2596.  
  2597. {
  2598. User procedure to refuse an exit for links
  2599. Note: may be unlink
  2600. }
  2601. procedure do_refuse(s: string);
  2602. var
  2603.     dir: integer;
  2604.     ok: boolean;
  2605.  
  2606. begin
  2607.     if not(is_owner) then
  2608.         { is_owner prints error message itself }
  2609.     else if lookup_dir(dir,s) then begin
  2610.         getroom;
  2611.         with here.exits[dir] do begin
  2612.             if (toloc = 0) and (kind = 5) then begin
  2613.                 kind := 0;
  2614.                 ok := true;
  2615.             end else
  2616.                 ok := false;
  2617.         end;
  2618.         putroom;
  2619.         if ok then begin
  2620.             log_event(myslot,E_REFUSE,0,0);
  2621.             writeln('Exits ',direct[dir],' will be refused.');
  2622.         end else
  2623.             writeln('Exits were not being accepted there.');
  2624.     end else
  2625.         writeln('To undo an Accept, type REFUSE <direction>.');
  2626. end;
  2627.  
  2628.  
  2629.  
  2630. function systime:string;
  2631. var
  2632.     hourstring: string;
  2633.     hours: integer;
  2634.     thetime: packed array[1..11] of char;
  2635.     dayornite: string;
  2636.  
  2637. begin
  2638.     time(thetime);
  2639.     if thetime[1] = ' ' then
  2640.         hours := ord(thetime[2]) - ord('0')
  2641.     else
  2642.         hours := (ord(thetime[1]) - ord('0'))*10 +
  2643.               (ord(thetime[2]) - ord('0'));
  2644.  
  2645.     if hours < 12 then
  2646.         dayornite := 'am'
  2647.     else
  2648.         dayornite := 'pm';
  2649.     if hours >= 13 then
  2650.         hours := hours - 12;
  2651.     if hours = 0 then
  2652.         hours := 12;
  2653.  
  2654.     writev(hourstring,hours:2);
  2655.  
  2656.     systime := hourstring + ':' + thetime[4] + thetime[5] + dayornite;
  2657. end;
  2658.  
  2659.  
  2660.  
  2661. { substitute a parameter string for the # sign in the source string }
  2662. function subs_parm(s,parm: string): string;
  2663. var
  2664.     right,left: string;
  2665.     i: integer;        { i is point to break at }
  2666.  
  2667. begin
  2668.     i := index(s,'#');
  2669.     if (i > 0) and ((length(s) + length(parm)) <= 80) then begin
  2670.         if i >= length(s) then begin
  2671.             right := '';
  2672.             left := s;
  2673.         end else if i < 1 then begin
  2674.             right := s;
  2675.             left := '';
  2676.         end else begin
  2677.             right := substr(s,i+1,length(s)-i);
  2678.             left := substr(s,1,i);
  2679.         end;
  2680.         if length(left) <= 1 then
  2681.             left := ''
  2682.         else
  2683.             left := substr(left,1,length(left)-1);
  2684.  
  2685.         subs_parm := left + parm + right;
  2686.     end else begin
  2687.         subs_parm := s;
  2688.     end;
  2689. end;
  2690.  
  2691.  
  2692. procedure time_health;
  2693.  
  2694. begin
  2695.     if healthcycle > 0 then begin        { how quickly they heal }
  2696.         if myhealth < 7 then begin    { heal a little bit }
  2697.             myhealth := myhealth + 1;
  2698.  
  2699.             getroom;
  2700.             here.people[myslot].health := myhealth;
  2701.             putroom;
  2702.  
  2703.             {show new health rating }
  2704.         case myhealth of
  2705.             9: writeln('You are now in exceptional health.');
  2706.             8: writeln('You feel much stronger.  You are in better than average condition.');
  2707.             7: writeln('You are now in perfect health.');
  2708.             6: writeln('You only feel a little bit dazed now.');
  2709.             5: begin
  2710.                 writeln('You only have some minor cuts and abrasions now.  Most of your serious wounds');
  2711.                 writeln('have healed.');
  2712.                end;
  2713.             4: writeln('You are only suffering from some minor wounds now.');
  2714.             3: writeln('Your most serious wounds have healed, but you are still in bad shape.');
  2715.             2: writeln('You have healed somewhat, but are still very badly wounded.');
  2716.             1: writeln('You are in critical condition, but there may be hope.');
  2717.             0: writeln('are still dead.');
  2718.             otherwise writeln('You don''t seem to be in any condition at all.');
  2719.         end;
  2720.  
  2721.         putchars(chr(10)+old_prompt+line);
  2722.  
  2723.         end;
  2724.         healthcycle := 0;
  2725.     end else
  2726.         healthcycle := healthcycle + 1;
  2727. end;
  2728.  
  2729.  
  2730. procedure time_noises;
  2731. var
  2732.     n: integer;
  2733.  
  2734. begin
  2735.     if rnd100 <= 2 then begin
  2736.         n := rnd100;
  2737.         if n in [0..40] then
  2738.             log_event(0,E_NOISES,rnd100,0)
  2739.         else if n in [41..60] then
  2740.             log_event(0,E_ALTNOISE,rnd100,0);
  2741.     end;
  2742. end;
  2743.  
  2744.  
  2745. procedure time_trapdoor(silent: boolean);
  2746. var
  2747.     fall: boolean;
  2748.  
  2749. begin
  2750.     if rnd100 < here.trapchance then begin
  2751.             { trapdoor fires! }
  2752.  
  2753.         if here.trapto > 0 then begin
  2754.                 { logged action should cover {protected) }
  2755.             if {(protected) or} (logged_act) then
  2756.                 fall := false
  2757.             else if here.magicobj = 0 then
  2758.                 fall := true
  2759.             else if obj_hold(here.magicobj) then
  2760.                 fall := false
  2761.             else
  2762.                 fall := true;
  2763.         end else
  2764.             fall := false;
  2765.  
  2766.         if fall then begin
  2767.             do_exit(here.trapto);
  2768.             if not(silent) then
  2769.                 putchars(chr(10)+old_prompt+line);
  2770.         end;
  2771.     end;
  2772. end;
  2773.  
  2774.  
  2775. procedure time_midnight;
  2776.  
  2777. begin
  2778.     if systime = '12:00am' then
  2779.         log_event(0,E_MIDNIGHT,rnd100,0);
  2780. end;
  2781.  
  2782.  
  2783. { cause random events to occurr (ha ha ha) }
  2784.  
  2785. procedure rnd_event(silent: boolean := false);
  2786. var
  2787.     n: integer;
  2788.  
  2789. begin
  2790.     if rndcycle = 200 then begin    { inside here 3 times/min }
  2791.  
  2792.         time_noises;
  2793.         time_health;
  2794.         time_trapdoor(silent);
  2795.         time_midnight;
  2796.  
  2797.         rndcycle := 0;
  2798.     end else
  2799.         rndcycle := rndcycle + 1;
  2800. end;
  2801.  
  2802.  
  2803. procedure do_die;
  2804. var
  2805.     some: boolean;
  2806.  
  2807. begin
  2808.     writeln;
  2809.     writeln('        *** You have died ***');
  2810.     writeln;
  2811.     some := drop_everything;
  2812.     myhealth := 7;
  2813.     take_token(myslot,location);
  2814.     log_event(0,E_DIED,0,0,myname);
  2815.     if put_token(2,myslot) then begin
  2816.         location := 2;
  2817.         inmem := false;
  2818.         setevent;
  2819. { log entry to death loc }
  2820. { perhaps turn off refs to other people }
  2821.     end else begin
  2822.         writeln('The Monster universe regrets to inform you that you cannot be ressurected at');
  2823.         writeln('the moment.');
  2824.         halt;
  2825.     end;
  2826. end;
  2827.  
  2828.  
  2829. procedure poor_health(p: integer);
  2830. var
  2831.     some: boolean;
  2832.  
  2833. begin
  2834.     if myhealth > p then begin
  2835.         myhealth := myhealth - 1;
  2836.         getroom;
  2837.         here.people[myslot].health := myhealth;
  2838.         putroom;
  2839.         log_event(myslot,E_WEAKER,myhealth,0);
  2840.  
  2841.         { show new health rating }
  2842.         write('You ');
  2843.         case here.people[myslot].health of
  2844.             9: writeln('are still in exceptional health.');
  2845.             8: writeln('feel weaker, but are in better than average condition.');
  2846.             7: writeln('are somewhat weaker, but are in perfect health.');
  2847.             6: writeln('feel a little bit dazed.');
  2848.             5: writeln('have some minor cuts and abrasions.');
  2849.             4: writeln('have some wounds, but are still fairly strong.');
  2850.             3: writeln('are suffering from some serious wounds.'); 
  2851.             2: writeln('are very badly wounded.');
  2852.             1: writeln('have many serious wounds, and are near death.');
  2853.             0: writeln('are dead.');
  2854.             otherwise writeln('don''t seem to be in any condition at all.');
  2855.         end;
  2856.     end else begin { they died }
  2857.         do_die;
  2858.     end;
  2859. end;
  2860.  
  2861.  
  2862.  
  2863. { count objects here }
  2864.  
  2865. function find_numobjs: integer;
  2866. var
  2867.     sum,i: integer;
  2868.  
  2869. begin
  2870.     sum := 0;
  2871.     for i := 1 to maxobjs do
  2872.         if here.objs[i] <> 0 then
  2873.             sum := sum + 1;
  2874.     find_numobjs := sum;
  2875. end;
  2876.  
  2877.  
  2878.  
  2879. { optional parameter is slot of player's objects to count }
  2880.  
  2881. function find_numhold(player: integer := 0): integer;
  2882. var
  2883.     sum,i: integer;
  2884.  
  2885. begin
  2886.     if player = 0 then
  2887.         player := myslot;
  2888.  
  2889.     sum := 0;
  2890.     for i := 1 to maxhold do
  2891.         if here.people[player].holding[i] <> 0 then
  2892.             sum := sum + 1;
  2893.     find_numhold := sum;
  2894. end;
  2895.  
  2896.  
  2897.  
  2898.  
  2899. procedure take_hit(p: integer);
  2900. var
  2901.     i: integer;
  2902.  
  2903. begin
  2904.     if p > 0 then begin
  2905.         if rnd100 < (55 + (p-1) * 30) then { chance that they're hit }
  2906.             poor_health(p);
  2907.  
  2908.         if find_numobjs < maxobjs + 1 then begin
  2909.             { maybe they drop something if they're hit }
  2910.             for i := 1 to p do
  2911.                 maybe_drop;
  2912.         end;
  2913.     end;
  2914. end;
  2915.  
  2916.  
  2917. function punch_force(sock: integer): integer;
  2918. var
  2919.     p: integer;
  2920.  
  2921. begin
  2922.     if sock in [2,3,6,7,8,11,12] then    { no punch or a graze }
  2923.         p := 0
  2924.     else if sock in [4,9,10] then    { hard punches }
  2925.         p := 2
  2926.     else    { 1,5,13,14,15 }
  2927.         p := 1;        { all others are medium punches }
  2928.     punch_force := p;
  2929. end;
  2930.  
  2931. procedure put_punch(sock: integer;s: string);
  2932.  
  2933. begin
  2934.     case sock of
  2935.         1: writeln('You deliver a quick jab to ',s,'''s jaw.');
  2936.         2: writeln('You swing at ',s,' and miss.');
  2937.         3: writeln('A quick punch, but it only grazes ',s,'.');
  2938.         4: writeln(s,' doubles over after your jab to the stomach.');
  2939.         5: writeln('Your punch lands square on ',s,'''s face!');
  2940.         6: writeln('You swing wild and miss.');
  2941.         7: writeln('A good swing, but it misses ',s,' by a mile!');
  2942.         8: writeln('Your punch is blocked by ',s,'.');
  2943.         9: writeln('Your roundhouse blow sends ',s,' reeling.');
  2944.         10:writeln('You land a solid uppercut on ',s,'''s chin.');
  2945.         11:writeln(s,' fends off your blow.');
  2946.         12:writeln(s,' ducks and avoids your punch.');
  2947.         13:writeln('You thump ',s,' in the ribs.');
  2948.         14:writeln('You catch ',s,'''s face on your elbow.');
  2949.         15:writeln('You knock the wind out of ',s,' with a punch to the chest.');
  2950.     end;
  2951. end;
  2952.  
  2953.  
  2954. procedure get_punch(sock: integer;s: string);
  2955.  
  2956. begin
  2957.     case sock of
  2958.         1: writeln(s,' delivers a quick jab to your jaw!');
  2959.         2: writeln(s,' swings at you but misses.');
  2960.         3: writeln(s,'''s fist grazes you.');
  2961.         4: writeln('You double over after ',s,' lands a mean jab to your stomach!');
  2962.         5: writeln('You see stars as ',s,' bashes you in the face.');
  2963.         6: writeln('You only feel the breeze as ',s,' swings wildly.');
  2964.         7: writeln(s,'''s swing misses you by a yard.');
  2965.         8: writeln('With lightning reflexes you block ',s,'''s punch.');
  2966.         9: writeln(s,'''s blow sends you reeling.');
  2967.         10:writeln('Your head snaps back from ',s,'''s uppercut!');
  2968.         11:writeln('You parry ',s,'''s attack.');
  2969.         12:writeln('You duck in time to avoid ',s,'''s punch.');
  2970.         13:writeln(s,' thumps you hard in the ribs.');
  2971.         14:writeln('Your vision blurs as ',s,' elbows you in the head.');
  2972.         15:writeln(s,' knocks the wind out of you with a punch to your chest.');
  2973.     end;
  2974. end;
  2975.  
  2976. procedure view_punch(a,b: string;p: integer);
  2977.  
  2978. begin
  2979.     case p of
  2980.         1: writeln(a,' jabs ',b,' in the jaw.');
  2981.         2: writeln(a,' throws a wild punch at the air.');
  2982.         3: writeln(a,'''s fist barely grazes ',b,'.');
  2983.         4: writeln(b,' doubles over in pain with ',a,'''s punch');
  2984.         5: writeln(a,' bashes ',b,' in the face.');
  2985.         6: writeln(a,' takes a wild swing at ',b,' and misses.');
  2986.         7: writeln(a,' swings at ',b,' and misses by a yard.');
  2987.         8: writeln(b,'''s punch is blocked by ',a,'''s quick reflexes.');
  2988.         9: writeln(b,' is sent reeling from a punch by ',a,'.');
  2989.         10:writeln(a,' lands an uppercut on ',b,'''s head.');
  2990.         11:writeln(b,' parrys ',a,'''s attack.');
  2991.         12:writeln(b,' ducks to avoid ',a,'''s punch.');
  2992.         13:writeln(a,' thumps ',b,' hard in the ribs.');
  2993.         14:writeln(a,'''s elbow connects with ',b,'''s head.');
  2994.         15:writeln(a,' knocks the wind out of ',b,'.');
  2995.     end;
  2996. end;
  2997.  
  2998.  
  2999.  
  3000.  
  3001. procedure desc_health(n: integer;header:shortstring := '');
  3002.  
  3003. begin
  3004.     if header = '' then
  3005.         write(here.people[n].name,' ')
  3006.     else
  3007.         write(header);
  3008.  
  3009.     case here.people[n].health of
  3010.         9: writeln('is in exceptional health, and looks very strong.');
  3011.         8: writeln('is in better than average condition.');
  3012.         7: writeln('is in perfect health.');
  3013.         6: writeln('looks a little dazed.');
  3014.         5: writeln('has some minor cuts and abrasions.');
  3015.         4: writeln('has some minor wounds.');
  3016.         3: writeln('is suffering from some serious wounds.'); 
  3017.         2: writeln('is very badly wounded.');
  3018.         1: writeln('has many serious wounds, and is near death.');
  3019.         0: writeln('is dead.');
  3020.         otherwise writeln('doesn''t seem to be in any condition at all.');
  3021.     end;
  3022. end;
  3023.  
  3024.  
  3025. function obj_part(objnum: integer;doread: boolean := TRUE): string;
  3026. var
  3027.     s: string;
  3028.  
  3029. begin
  3030.     if doread then begin
  3031.         getobj(objnum);
  3032.         freeobj;
  3033.     end;
  3034.     s := obj.oname;
  3035.     case obj.particle of
  3036.         0:;
  3037.         1: s := 'a ' + s;
  3038.         2: s := 'an ' + s;
  3039.         3: s := 'some ' + s;
  3040.         4: s := 'the ' + s;
  3041.     end;
  3042.     obj_part := s;
  3043. end;
  3044.  
  3045.  
  3046. procedure print_subs(n: integer;s: string);
  3047.  
  3048. begin
  3049.     if (n > 0) and (n <> DEFAULT_LINE) then begin
  3050.         getline(n);
  3051.         freeline;
  3052.         writeln(subs_parm(oneliner.theline,s));
  3053.     end else if n = DEFAULT_LINE then
  3054.         writeln('%<default line> in print_subs');
  3055. end;
  3056.  
  3057.  
  3058.  
  3059. { print out a (up to) 10 line description block, substituting string s for
  3060.   up to one occurance of # per line }
  3061.  
  3062. procedure block_subs(n: integer;s: string);
  3063. var
  3064.     p,i: integer;
  3065.  
  3066. begin
  3067.     if n < 0 then
  3068.         print_subs(abs(n),s)
  3069.     else if (n > 0) and (n <> DEFAULT_LINE) then begin
  3070.         getblock(n);
  3071.         freeblock;
  3072.         i := 1;
  3073.         while i <= block.desclen do begin
  3074.             p := index(block.lines[i],'#');
  3075.             if (p > 0) then
  3076.                 writeln(subs_parm(block.lines[i],s))
  3077.             else
  3078.                 writeln(block.lines[i]);
  3079.             i := i + 1;
  3080.         end;
  3081.     end;
  3082. end;
  3083.  
  3084.  
  3085. procedure show_noises(n: integer);
  3086.  
  3087. begin
  3088.     if n < 33 then
  3089.         writeln('There are strange noises coming from behind you.')
  3090.     else if n < 66 then
  3091.         writeln('You hear strange rustling noises behind you.')
  3092.     else
  3093.         writeln('There are faint noises coming from behind you.');
  3094. end;
  3095.  
  3096.  
  3097. procedure show_altnoise(n: integer);
  3098.  
  3099. begin
  3100.     if n < 33 then
  3101.         writeln('A chill wind blows, ruffling your clothes and chilling your bones.')
  3102.     else if n < 66 then
  3103.         writeln('Muffled scuffling sounds can be heard behind you.')
  3104.     else
  3105.         writeln('A loud crash can be heard in the distance.');
  3106. end;
  3107.  
  3108.  
  3109. procedure show_midnight(n: integer;var printed: boolean);
  3110.  
  3111. begin
  3112.     if midnight_notyet then begin
  3113.         if n < 50 then begin
  3114.             writeln('A voice booms out of the air from all around you!');
  3115.             writeln('The voice says,  " It is now midnight. "');
  3116.         end else begin
  3117.             writeln('You hear a clock chiming in the distance.');
  3118.             writeln('It rings twelve times for midnight.');
  3119.         end;
  3120.         midnight_notyet := false;
  3121.     end else
  3122.         printed := false;
  3123. end;
  3124.  
  3125.  
  3126.  
  3127.  
  3128. procedure handle_event(var printed: boolean);
  3129. var
  3130.     n,send,act,targ,p: integer;
  3131.     s: string;
  3132.     sendname: string;
  3133.  
  3134. begin
  3135.     printed := true;
  3136.     if debug then
  3137.         writeln('%handling event ',myevent);
  3138.     with event.evnt[myevent] do begin
  3139.         send := sender;
  3140.         act := action;
  3141.         targ := target;
  3142.         p := parm;
  3143.         s := msg;
  3144.     end;
  3145.     if send <> 0 then
  3146.         sendname := here.people[send].name
  3147.     else
  3148.         sendname := '<Unknown>';
  3149.  
  3150.     case act of
  3151.         E_EXIT: begin
  3152.                 if here.exits[targ].goin = DEFAULT_LINE then
  3153.                     writeln(s,' has gone ',direct[targ],'.')
  3154.                 else if (here.exits[targ].goin <> 0) and
  3155.                 (here.exits[targ].goin <> DEFAULT_LINE) then begin
  3156.                     block_subs(here.exits[targ].goin,s);
  3157.                 end else
  3158.                     printed := false;
  3159.             end;
  3160.         E_ENTER: begin
  3161.                 if here.exits[targ].comeout = DEFAULT_LINE then
  3162.                     writeln(s,' has come into the room from: ',direct[targ])
  3163.                 else if (here.exits[targ].comeout <> 0) and
  3164.                 (here.exits[targ].comeout <> DEFAULT_LINE) then begin
  3165.                     block_subs(here.exits[targ].comeout,s);
  3166.                 end else
  3167.                     printed := false;
  3168.             end;
  3169.         E_BEGIN:writeln(s,' appears in a brilliant burst of multicolored light.');
  3170.         E_QUIT:writeln(s,' vanishes in a brilliant burst of multicolored light.');
  3171.         E_SAY: begin
  3172.             if length(s) + length(sendname) > 73 then begin
  3173.                 writeln(sendname,' says,');
  3174.                 writeln('"',s,'"');
  3175.             end else begin
  3176.                 if (rnd100 < 50) or (length(s) > 50) then
  3177.                     writeln(sendname,': "',s,'"')
  3178.                 else
  3179.                     writeln(sendname,' says, "',s,'"');
  3180.             end;
  3181.                end;
  3182.         E_HIDESAY: begin
  3183.                 writeln('An unidentified voice speaks to you:');
  3184.                 writeln('"',s,'"');
  3185.                end;
  3186.         E_SETNAM: writeln(s);
  3187.         E_POOFIN: writeln('In an explosion of orange smoke ',s,' poofs into the room.');
  3188.         E_POOFOUT: writeln(s,' vanishes from the room in a cloud of orange smoke.');
  3189.         E_DETACH: begin
  3190.                 writeln(s,' has destroyed the exit ',direct[targ],'.');
  3191.               end;
  3192.         E_EDITDONE:begin
  3193.                 writeln(sendname,' is done editing the room description.');
  3194.                end;
  3195.         E_NEWEXIT: begin
  3196.                 writeln(s,' has created an exit here.');
  3197.                end;
  3198.         E_CUSTDONE:begin
  3199.                 writeln(sendname,' is done customizing an exit here.');
  3200.                end;
  3201.         E_SEARCH: writeln(sendname,' seems to be looking for something.');
  3202.         E_FOUND: writeln(sendname,' appears to have found something.');
  3203.         E_DONEDET:begin
  3204.                 writeln(sendname,' is done adding details to the room.');
  3205.               end;
  3206.         E_ROOMDONE: begin
  3207.                 writeln(sendname,' is finished customizing this room.');
  3208.                 end;
  3209.         E_OBJDONE: begin
  3210.                 writeln(sendname,' is finished customizing an object.');
  3211.                end;
  3212.         E_UNHIDE:writeln(sendname,' has stepped out of the shadows.');
  3213.         E_FOUNDYOU: begin
  3214.                 if targ = myslot then begin { found me! }
  3215.                     writeln('You''ve been discovered by ',sendname,'!');
  3216.                     hiding := false;
  3217.                     getroom;
  3218. { they're not hidden anymore }        here.people[myslot].hiding := 0;
  3219.                     putroom;
  3220.                 end else
  3221.                     writeln(sendname,' has found ',here.people[targ].name,' hiding in the shadows!');
  3222.                 end;
  3223.         E_PUNCH: begin
  3224.                 if targ = myslot then begin { punched me! }
  3225.                     get_punch(p,sendname);
  3226.                     take_hit( punch_force(p) );
  3227. { relic, but not harmful }        ping_answered := true;
  3228.                     healthcycle := 0;
  3229.                 end else
  3230.                     view_punch(sendname,here.people[targ].name,p);
  3231.              end;
  3232.         E_MADEOBJ: writeln(s);
  3233.         E_GET: writeln(s);
  3234.         E_DROP: begin
  3235.                 writeln(s);
  3236.                 if here.objdesc <> 0 then
  3237.                     print_subs(here.objdesc,obj_part(p));
  3238.             end;
  3239.         E_BOUNCEDIN: begin
  3240.                 if (targ = 0) or (targ = DEFAULT_LINE) then
  3241.                     writeln(obj_part(p),' has bounced into the room.')
  3242.                 else begin
  3243.                     print_subs(targ,obj_part(p));
  3244.                 end;
  3245.                  end;
  3246.         E_DROPALL: writeln('Some objects drop to the ground.');
  3247.         E_EXAMINE: writeln(s);
  3248.         E_IHID: writeln(sendname,' has hidden in the shadows.');
  3249.         E_NOISES: begin
  3250.                 if (here.rndmsg = 0) or
  3251.                    (here.rndmsg = DEFAULT_LINE) then begin
  3252.                     show_noises(targ);
  3253.                 end else
  3254.                     print_line(here.rndmsg);
  3255.               end;
  3256.         E_ALTNOISE: begin
  3257.                 if (here.xmsg2 = 0) or
  3258.                    (here.xmsg2 = DEFAULT_LINE) then
  3259.                     show_altnoise(targ)
  3260.                 else
  3261.                     block_subs(here.xmsg2,myname);
  3262.                 end;
  3263.         E_REALNOISE: show_noises(targ);
  3264.         E_HIDOBJ: writeln(sendname,' has hidden the ',s,'.');
  3265.         E_PING: begin
  3266.                 if targ = myslot then begin
  3267.                     writeln(sendname,' is trying to ping you.');
  3268.                     log_event(myslot,E_PONG,send,0);
  3269.                 end else
  3270.                     writeln(sendname,' is pinging ',here.people[targ].name,'.');
  3271.             end;
  3272.         E_PONG: begin
  3273.                 ping_answered := true;
  3274.             end;
  3275.         E_HIDEPUNCH: begin
  3276.                 if targ = myslot then begin
  3277.                     writeln(sendname,' pounces on you from the shadows!');
  3278.                     take_hit(2);
  3279.                 end else begin
  3280.                     writeln(sendname,' jumps out of the shadows and attacks ',here.people[targ].name,'.');
  3281.                 end;
  3282.                  end;
  3283.         E_SLIPPED: begin
  3284.                 writeln('The ',s,' has slipped from ',
  3285.                     sendname,'''s hands.');
  3286.                end;
  3287.         E_HPOOFOUT:begin
  3288.                 if rnd100 > 50 then
  3289.                     writeln('Great wisps of orange smoke drift out of the shadows.')
  3290.                 else
  3291.                     printed := false;
  3292.                end;
  3293.         E_HPOOFIN:begin
  3294.                 if rnd100 > 50 then
  3295.                     writeln('Some wisps of orange smoke drift about in the shadows.')
  3296.                 else
  3297.                     printed := false;
  3298.               end;
  3299.         E_FAILGO: begin
  3300.                 if targ > 0 then begin
  3301.                     write(sendname,' has failed to go ');
  3302.                     writeln(direct[targ],'.');
  3303.                 end;
  3304.               end;
  3305.         E_TRYPUNCH: begin
  3306.                 if targ = myslot then
  3307.                     writeln(sendname,' fails to punch you.')
  3308.                 else
  3309.                     writeln(sendname,' fails to punch ',here.people[targ].name,'.');
  3310.                 end;
  3311.         E_PINGONE:begin
  3312.                 if targ = myslot then begin { ohoh---pinged away }
  3313.                     writeln('The Monster program regrets to inform you that a destructive ping has');
  3314.                     writeln('destroyed your existence.  Please accept our apologies.');
  3315.                     halt;  { ugggg }
  3316.                 end else
  3317.                     writeln(s,' shimmers and vanishes from sight.');
  3318.               end;
  3319.         E_CLAIM: writeln(sendname,' has claimed this room.');
  3320.         E_DISOWN: writeln(sendname,' has disowned this room.');
  3321.         E_WEAKER: begin
  3322. {                inmem := false;
  3323.                 gethere;        }
  3324.  
  3325.                 here.people[send].health := targ;
  3326.  
  3327. { This is a hack for efficiency so we don't read the room record twice;
  3328.   we need the current data now for desc_health, but checkevents, our caller,
  3329.   is about to re-read it anyway; we make an incremental fix here so desc_health
  3330.   is happy, then checkevents will do the real read later }
  3331.  
  3332.                 desc_health(send);
  3333.               end;
  3334.         E_OBJCLAIM: writeln(sendname,' is now the owner of the ',s,'.');
  3335.         E_OBJDISOWN: writeln(sendname,' has disowned the object ',s,'.');
  3336.         E_SELFDONE: writeln(sendname,'''s self-description is finished.');
  3337.         E_WHISPER: begin
  3338.                 if targ = myslot then begin
  3339.                     if length(s) < 39 then
  3340.                         writeln(sendname,' whispers to you, "',s,'"')
  3341.                     else begin
  3342.                         writeln(sendname,' whispers something to you:');
  3343.                         write(sendname,' whispers, ');
  3344.                         if length(s) > 50 then
  3345.                             writeln;
  3346.                         writeln('"',s,'"');
  3347.                     end;
  3348.                 end else if (privd) or (rnd100 > 85) then begin
  3349.                     writeln('You overhear ',sendname,' whispering to ',here.people[targ].name,'!');
  3350.                     write(sendname,' whispers, ');
  3351.                     if length(s) > 50 then
  3352.                         writeln;
  3353.                     writeln('"',s,'"');
  3354.                 end else
  3355.                     writeln(sendname,' is whispering to ',here.people[targ].name,'.');
  3356.                end;
  3357.         E_WIELD: writeln(sendname,' is now wielding the ',s,'.');
  3358.         E_UNWIELD: writeln(sendname,' is no longer wielding the ',s,'.');
  3359.         E_WEAR: writeln(sendname,' is now wearing the ',s,'.');
  3360.         E_UNWEAR: writeln(sendname,' has taken off the ',s,'.');
  3361.         E_DONECRYSTALUSE: begin
  3362.                     writeln(sendname,' emerges from the glow of the crystal.');
  3363.                     writeln('The orb becomes dark.');
  3364.                   end;
  3365.         E_DESTROY: writeln(s);
  3366.         E_OBJPUBLIC: writeln('The object ',s,' is now public.');
  3367.         E_SYSDONE: writeln(sendname,' is no longer in system maintenance mode.');
  3368.         E_UNMAKE: writeln(sendname,' has unmade ',s,'.');
  3369.         E_LOOKDETAIL: writeln(sendname,' is looking at the ',s,'.');
  3370.         E_ACCEPT: writeln(sendname,' has accepted an exit here.');
  3371.         E_REFUSE: writeln(sendname,' has refused an Accept here.');
  3372.         E_DIED: writeln(s,' expires and vanishes in a cloud of greasy black smoke.');
  3373.         E_LOOKYOU: begin
  3374.                 if targ = myslot then begin
  3375.                     writeln(sendname,' is looking at you.')
  3376.                 end else
  3377.                     writeln(sendname,' looks at ',here.people[targ].name,'.');
  3378.                end;
  3379.         E_LOOKSELF: writeln(sendname,' is making a self-appraisal.');
  3380.         E_FAILGET: writeln(sendname,' fails to get ',obj_part(targ),'.');
  3381.         E_FAILUSE: writeln(sendname,' fails to use ',obj_part(targ),'.');
  3382.         E_CHILL: if (targ = 0) or (targ = DEFAULT_LINE) then
  3383.                 writeln('A chill wind blows over you.')
  3384.              else
  3385.                 print_desc(targ);
  3386.         E_NOISE2:begin
  3387.                 case targ of
  3388.                     1: writeln('Strange, gutteral noises sound from everywhere.');
  3389.                     2: writeln('A chill wind blows past you, almost whispering as it ruffles your clothes.');
  3390.                     3: writeln('Muffled voices speak to you from the air!');
  3391.                     otherwise writeln('The air vibrates with a chill shudder.');
  3392.                 end;
  3393.              end;
  3394.         E_INVENT: writeln(sendname,' is taking inventory.');
  3395.         E_POOFYOU: begin
  3396.                 if targ = myslot then begin
  3397.                     writeln;
  3398.                     writeln(sendname,' directs a firey burst of bluish energy at you!');
  3399.                     writeln('Suddenly, you find yourself hurtling downwards through misty orange clouds.');
  3400.                     writeln('Your descent slows, the smoke clears, and you find yourself in a new place...');
  3401.                     xpoof(p);
  3402.                     writeln;
  3403.                 end else begin
  3404.                     writeln(sendname,' directs a firey burst of energy at ',here.people[targ].name,'!');
  3405.                     writeln('A thick burst of orange smoke results, and when it clears, you see');
  3406.                     writeln('that ',here.people[targ].name,' is gone.');
  3407.                 end;
  3408.                end;
  3409.         E_WHO: begin
  3410.             case p of
  3411.                 0: writeln(sendname,' produces a "who" list and reads it.');
  3412.                 1: writeln(sendname,' is seeing who''s playing Monster.');
  3413.                 otherwise writeln(sendname,' checks the "who" list.');
  3414.             end;
  3415.                end;
  3416.         E_PLAYERS:begin
  3417.                 writeln(sendname,' checks the "players" list.');
  3418.               end;
  3419.         E_VIEWSELF: writeln(sendname,' is reading ',s,'''s self-description.');
  3420.         E_MIDNIGHT: show_midnight(targ,printed);
  3421.  
  3422.         E_ACTION:writeln(sendname,' is',desc_action(p,targ));
  3423.         otherwise writeln('*** Bad Event ***');
  3424.     end;
  3425. end;
  3426.  
  3427.  
  3428. [global]
  3429. procedure checkevents(silent: boolean := false);
  3430. var
  3431.     gotone: boolean;
  3432.     tmp,printed: boolean;
  3433.  
  3434. begin
  3435.     getevent;
  3436.     freeevent;
  3437.  
  3438.     event := eventfile^;
  3439.     gotone := false;
  3440.     printed := false;
  3441.     while myevent <> event.point do begin
  3442.         myevent := myevent + 1;
  3443.         if myevent > maxevent then
  3444.             myevent := 1;
  3445.  
  3446.         if debug then begin
  3447.             writeln('%checking event ',myevent);
  3448.             if event.evnt[myevent].loc = location then
  3449.                 writeln('  - event here')
  3450.             else
  3451.                 writeln('  - event elsewhere');
  3452.             writeln('  - event number = ',event.evnt[myevent].action:1);
  3453.         end;
  3454.  
  3455.         if (event.evnt[myevent].loc = location) then begin
  3456.             if (event.evnt[myevent].sender <> myslot) then begin
  3457.  
  3458.                         { if sent by me don't look at it }
  3459.                         { will use global record event }
  3460.                 handle_event(tmp);
  3461.                 if tmp then
  3462.                     printed := true;
  3463.  
  3464.                 inmem := false;    { re-read important data that }
  3465.                 gethere;    { may have been altered }
  3466.  
  3467.                 gotone := true;
  3468.             end;
  3469.         end;
  3470.     end;
  3471.     if (printed) and (gotone) and not(silent) then begin
  3472.         putchars(chr(10)+chr(13)+old_prompt+line);
  3473.     end;
  3474.  
  3475.     rnd_event(silent);
  3476. end;
  3477.  
  3478.  
  3479.  
  3480. { count the number of people in this room; assumes a gethere has been done }
  3481.  
  3482. function find_numpeople: integer;
  3483. var
  3484.     sum,i: integer;
  3485.  
  3486. begin
  3487.     sum := 0;
  3488.     for i := 1 to maxpeople do
  3489.         if here.people[i].kind > 0 then
  3490. {        if here.people[i].username <> '' then    }
  3491.             sum := sum + 1;
  3492.     find_numpeople := sum;
  3493. end;
  3494.  
  3495.  
  3496.  
  3497. { don't give them away, but make noise--maybe
  3498.   percent is percentage chance that they WON'T make any noise }
  3499.  
  3500. procedure noisehide(percent: integer);
  3501.  
  3502. begin
  3503.     { assumed gethere;  }
  3504.     if (hiding) and (find_numpeople > 1) then begin
  3505.         if rnd100 > percent then
  3506.             log_event(myslot,E_REALNOISE,rnd100,0);
  3507.             { myslot: don't tell them they made noise }
  3508.     end;
  3509. end;
  3510.  
  3511.  
  3512.  
  3513. function checkhide: boolean;
  3514.  
  3515. begin
  3516.     if (hiding) then begin
  3517.         checkhide := false;
  3518.         noisehide(50);
  3519.         writeln('You can''t do that while you''re hiding.');
  3520.     end else
  3521.         checkhide := true;
  3522. end;
  3523.  
  3524.  
  3525.  
  3526. procedure clear_command;
  3527.  
  3528. begin
  3529.     if logged_act then begin
  3530.         getroom;
  3531.         here.people[myslot].act := 0;
  3532.         putroom;
  3533.         logged_act := false;
  3534.     end;
  3535. end;
  3536.  
  3537. { forward procedure take_token(aslot, roomno: integer); }
  3538. procedure take_token;
  3539.             { remove self from a room's people list }
  3540.  
  3541. begin
  3542.     getroom(roomno);
  3543.     with here.people[aslot] do begin
  3544.         kind := 0;
  3545.         username:= '';
  3546.         name := '';
  3547.     end;
  3548.     putroom;
  3549. end;
  3550.  
  3551.  
  3552. { fowrard function put_token(room: integer;var aslot:integer;
  3553.     hidelev:integer := 0):boolean;
  3554.              put a person in a room's people list
  3555.              returns myslot }
  3556. function put_token;
  3557. var
  3558.     i,j: integer;
  3559.     found: boolean;
  3560.     savehold: array[1..maxhold] of integer;
  3561.  
  3562. begin
  3563.     if first_puttoken then begin
  3564.         for i := 1 to maxhold do
  3565.             savehold[i] := 0;
  3566.         first_puttoken := false;
  3567.     end else begin
  3568.         gethere;
  3569.         for i := 1 to maxhold do
  3570.             savehold[i] := here.people[myslot].holding[i];
  3571.     end;
  3572.  
  3573.     getroom(room);
  3574.     i := 1;
  3575.     found := false;
  3576.     while (i <= maxpeople) and (not found) do begin
  3577.         if here.people[i].name = '' then
  3578.             found := true
  3579.         else
  3580.             i := i + 1;
  3581.     end;
  3582.     put_token := found;
  3583.     if found then begin
  3584.         here.people[i].kind := 1;    { I'm a real player }
  3585.         here.people[i].name := myname;
  3586.         here.people[i].username := userid;
  3587.         here.people[i].hiding := hidelev;
  3588.             { hidelev is zero for most everyone
  3589.               unless you want to poof in and remain hidden }
  3590.  
  3591.         here.people[i].wearing := mywear;
  3592.         here.people[i].wielding := mywield;
  3593.         here.people[i].health := myhealth;
  3594.         here.people[i].self := myself;
  3595.  
  3596.         here.people[i].act := 0;
  3597.  
  3598.         for j := 1 to maxhold do
  3599.             here.people[i].holding[j] := savehold[j];
  3600.         putroom;
  3601.  
  3602.         aslot := i;
  3603.         for j := 1 to maxexit do    { haven't found any exits in }
  3604.             found_exit[j] := false;    { the new room }
  3605.  
  3606.         { note the user's new location in the logfile }
  3607.         getint(N_LOCATION); 
  3608.         anint.int[mylog] := room;
  3609.         putint;
  3610.     end else
  3611.         freeroom;
  3612. end;
  3613.  
  3614. procedure log_exit(direction,room,sender_slot: integer);
  3615.  
  3616. begin
  3617.     log_event(sender_slot,E_EXIT,direction,0,myname,room);
  3618. end;
  3619.  
  3620. procedure log_entry(direction,room,sender_slot: integer);
  3621.  
  3622. begin
  3623.     log_event(sender_slot,E_ENTER,direction,0,myname,room);
  3624. end;
  3625.  
  3626. procedure log_begin(room:integer := 1);
  3627.  
  3628. begin
  3629.     log_event(0,E_BEGIN,0,0,myname,room);
  3630. end;
  3631.  
  3632. procedure log_quit(room:integer;dropped:boolean);
  3633.  
  3634. begin
  3635.     log_event(0,E_QUIT,0,0,myname,room);
  3636.     if dropped then
  3637.         log_event(0,E_DROPALL,0,0,myname,room);
  3638. end;
  3639.  
  3640.  
  3641.  
  3642.  
  3643. { return the number of people you can see here }
  3644.  
  3645. function n_can_see: integer;
  3646. var
  3647.     sum: integer;
  3648.     i: integer;
  3649.     selfslot: integer;
  3650.  
  3651. begin
  3652.     if here.locnum = location then
  3653.         selfslot := myslot
  3654.     else
  3655.         selfslot := 0;
  3656.  
  3657.     sum := 0;
  3658.     for i := 1 to maxpeople do
  3659.         if ( i <> selfslot ) and
  3660.            ( length(here.people[i].name) > 0 ) and
  3661.            ( here.people[i].hiding = 0 ) then
  3662.             sum := sum + 1;
  3663.     n_can_see := sum;
  3664.     if debug then
  3665.         writeln('%n_can_see = ',sum:1);
  3666. end;
  3667.  
  3668.  
  3669.  
  3670. function next_can_see(var point: integer): string;
  3671. var
  3672.     found: boolean;
  3673.     selfslot: integer;
  3674.  
  3675. begin
  3676.     if here.locnum <> location then
  3677.         selfslot := 0
  3678.     else
  3679.         selfslot := myslot;
  3680.     found := false;
  3681.     while (not found) and (point <= maxpeople) do begin
  3682.         if (point <> selfslot) and
  3683.            (length(here.people[point].name) > 0) and
  3684.            (here.people[point].hiding = 0) then
  3685.             found := true
  3686.         else
  3687.             point := point + 1;
  3688.     end;
  3689.  
  3690.     if found then begin
  3691.         next_can_see := here.people[point].name;
  3692.         point := point + 1;
  3693.     end else begin
  3694.         next_can_see := myname;    { error!  error! }
  3695.         writeln('%searching error in next_can_see; notify the Monster Manager');
  3696.     end;
  3697. end;
  3698.  
  3699.  
  3700. procedure niceprint(var len: integer; s: string);
  3701.  
  3702. begin
  3703.     if len + length(s) > 78 then begin
  3704.         len := 0;
  3705.         writeln;
  3706.     end else begin
  3707.         len := len + length(s);
  3708.     end;
  3709.     write(s);
  3710. end;
  3711.  
  3712.  
  3713. procedure people_header(where: shortstring);
  3714. var
  3715.     point: integer;
  3716.     tmp: string;
  3717.     i: integer;
  3718.     n: integer;
  3719.     len: integer;
  3720.  
  3721. begin
  3722.     point := 1;
  3723.     n := n_can_see;
  3724.     case n of
  3725.         0:;
  3726.         1: begin
  3727.             writeln(next_can_see(point),' is ',where);
  3728.            end;
  3729.         2: begin
  3730.             writeln(next_can_see(point),' and ',next_can_see(point),
  3731.                 ' are ',where);
  3732.            end;
  3733.         otherwise begin
  3734.             len := 0;
  3735.             for i := 1 to n - 1 do begin { at least 1 to 2 }
  3736.                 tmp := next_can_see(point);
  3737.                 if i <> n - 1 then
  3738.                     tmp := tmp + ', ';
  3739.                 niceprint(len,tmp);
  3740.             end;
  3741.  
  3742.             niceprint(len,' and ');
  3743.             niceprint(len,next_can_see(point));
  3744.             niceprint(len,' are ' + where);
  3745.             writeln;
  3746.         end;
  3747.     end;
  3748. end;
  3749.  
  3750.  
  3751. procedure desc_person(i: integer);
  3752. var
  3753.     pname: shortstring;
  3754.  
  3755. begin
  3756.     pname := here.people[i].name;
  3757.  
  3758.     if here.people[i].act <> 0 then begin
  3759.         write(pname,' is');
  3760.         writeln(desc_action(here.people[i].act,
  3761.             here.people[i].targ));
  3762.                     { describes what person last did }
  3763.     end;
  3764.  
  3765.     if here.people[i].health <> GOODHEALTH then
  3766.         desc_health(i);
  3767.  
  3768.     if here.people[i].wielding > 0 then
  3769.         writeln(pname,' is wielding ',obj_part(here.people[i].wielding),'.');
  3770.  
  3771. end;
  3772.  
  3773.  
  3774. procedure show_people;
  3775. var
  3776.     i: integer;
  3777.  
  3778. begin
  3779.     people_header('here.');
  3780.     for i := 1 to maxpeople do begin
  3781.         if (here.people[i].name <> '') and
  3782.            (i <> myslot) and
  3783.            (here.people[i].hiding = 0) then
  3784.                 desc_person(i);
  3785.     end;
  3786. end;
  3787.  
  3788.  
  3789. procedure show_group;
  3790. var
  3791.     gloc1,gloc2: integer;
  3792.     gnam1,gnam2: shortstring;
  3793.  
  3794. begin
  3795.     gloc1 := here.grploc1;
  3796.     gloc2 := here.grploc2;
  3797.     gnam1 := here.grpnam1;
  3798.     gnam2 := here.grpnam2;
  3799.  
  3800.     if gloc1 <> 0 then begin
  3801.         gethere(gloc1);
  3802.         people_header(gnam1);
  3803.     end;
  3804.     if gloc2 <> 0 then begin
  3805.         gethere(gloc2);
  3806.         people_header(gnam2);
  3807.     end;
  3808.     gethere;
  3809. end;
  3810.  
  3811.  
  3812. procedure desc_obj(n: integer);
  3813.  
  3814. begin
  3815.     if n <> 0 then begin
  3816.         getobj(n);
  3817.         freeobj;
  3818.         if (obj.linedesc = DEFAULT_LINE) then begin
  3819.             writeln('On the ground here is ',obj_part(n,FALSE),'.');
  3820.  
  3821.                 { the FALSE means obj_part shouldn't do its
  3822.                   own getobj, cause we already did one }
  3823.         end else
  3824.             print_line(obj.linedesc);
  3825.     end;
  3826. end;
  3827.  
  3828.  
  3829. procedure show_objects;
  3830.  
  3831. var
  3832.     i: integer;
  3833.  
  3834. begin
  3835.     for i := 1 to maxobjs do begin
  3836.         if (here.objs[i] <> 0) and (here.objhide[i] = 0) then
  3837.             desc_obj(here.objs[i]);
  3838.     end;
  3839. end;
  3840.  
  3841.  
  3842. function lookup_detail(var n: integer;s:string): boolean;
  3843. var
  3844.     i,poss,maybe,num: integer;
  3845.  
  3846. begin
  3847.     n := 0;
  3848.     s := lowcase(s);
  3849.     i := 1;
  3850.     maybe := 0;
  3851.     num := 0;
  3852.     for i := 1 to maxdetail do begin
  3853.         if s = here.detail[i] then
  3854.             num := i
  3855.         else if index(here.detail[i],s) = 1 then begin
  3856.             maybe := maybe + 1;
  3857.             poss := i;
  3858.         end;
  3859.     end;
  3860.     if num <> 0 then begin
  3861.         n := num;
  3862.         lookup_detail := true;
  3863.     end else if maybe = 1 then begin
  3864.         n := poss;
  3865.         lookup_detail := true;
  3866.     end else if maybe > 1 then begin
  3867.         lookup_detail := false;
  3868.     end else begin
  3869.         lookup_detail := false;
  3870.     end;
  3871. end;
  3872.  
  3873.  
  3874. function look_detail(s: string): boolean;
  3875. var
  3876.     n: integer;
  3877.  
  3878. begin
  3879.     if lookup_detail(n,s) then begin
  3880.         if here.detaildesc[n] = 0 then
  3881.             look_detail := false
  3882.         else begin
  3883.             print_desc(here.detaildesc[n]);
  3884.             log_event(myslot,E_LOOKDETAIL,0,0,here.detail[n]);
  3885.             look_detail := true;
  3886.         end;
  3887.     end else
  3888.         look_detail := false;
  3889. end;
  3890.  
  3891.  
  3892. function look_person(s: string): boolean;
  3893. var
  3894.     objnum,i,n: integer;
  3895.     first: boolean;
  3896.  
  3897. begin
  3898.     if parse_pers(n,s) then begin
  3899.         if n = myslot then begin
  3900.             log_event(myslot,E_LOOKSELF,n,0);
  3901.             writeln('You step outside of yourself for a moment to get an objective self-appraisal:');
  3902.             writeln;
  3903.         end else
  3904.             log_event(myslot,E_LOOKYOU,n,0);
  3905.         if here.people[n].self <> 0 then begin
  3906.             print_desc(here.people[n].self);
  3907.             writeln;
  3908.         end;
  3909.  
  3910.         desc_health(n);
  3911.  
  3912.             { Do an inventory of person S }
  3913.         first := true;
  3914.         for i := 1 to maxhold do begin
  3915.             objnum := here.people[n].holding[i];
  3916.             if objnum <> 0 then begin
  3917.                 if first then begin
  3918.                     writeln(here.people[n].name,' is holding:');
  3919.                     first := false;
  3920.                 end;
  3921.                 writeln('   ',obj_part(objnum));
  3922.             end;
  3923.         end;
  3924.         if first then
  3925.             writeln(here.people[n].name,' is empty handed.');
  3926.  
  3927.         look_person := true;
  3928.     end else
  3929.         look_person := false;
  3930. end;
  3931.  
  3932.  
  3933.  
  3934. procedure do_examine(s: string;var three: boolean;silent:boolean := false);
  3935. var
  3936.     n: integer;
  3937.     msg: string;
  3938.  
  3939. begin
  3940.     three := false;
  3941.     if parse_obj(n,s) then begin
  3942.         if obj_here(n) or obj_hold(n) then begin
  3943.             three := true;
  3944.  
  3945.             getobj(n);
  3946.             freeobj;
  3947.             msg := myname + ' is examining ' + obj_part(n) + '.';
  3948.             log_event(myslot,E_EXAMINE,0,0,msg);
  3949.             if obj.examine = 0 then
  3950.                 writeln('You see nothing special about the ',
  3951.                         objnam.idents[n],'.')
  3952.             else
  3953.                 print_desc(obj.examine);
  3954.         end else
  3955.             if not(silent) then
  3956.                 writeln('That object cannot be seen here.');
  3957.     end else
  3958.         if not(silent) then
  3959.             writeln('That object cannot be seen here.');
  3960. end;
  3961.  
  3962.  
  3963.  
  3964. procedure print_room;
  3965.  
  3966. begin
  3967.     case here.nameprint of
  3968.         0:;    { don't print name }
  3969.         1: writeln('You''re in ',here.nicename);
  3970.         2: writeln('You''re at ',here.nicename);
  3971.     end;
  3972.  
  3973.     if not(brief) then begin
  3974.     case here.which of
  3975.         0: print_desc(here.primary);
  3976.         1: print_desc(here.secondary);
  3977.         2: begin
  3978.             print_desc(here.primary);
  3979.             print_desc(here.secondary);
  3980.            end;
  3981.         3: begin
  3982.             print_desc(here.primary);
  3983.             if here.magicobj <> 0 then
  3984.                 if obj_hold(here.magicobj) then
  3985.                     print_desc(here.secondary);
  3986.            end;
  3987.         4: begin
  3988.             if here.magicobj <> 0 then begin
  3989.                 if obj_hold(here.magicobj) then
  3990.                     print_desc(here.secondary)
  3991.                 else
  3992.                     print_desc(here.primary);
  3993.             end else
  3994.                 print_desc(here.primary);
  3995.            end;
  3996.     end;
  3997.     writeln;
  3998.     end;   { if not(brief) }
  3999. end;
  4000.  
  4001.  
  4002.  
  4003. procedure do_look(s: string := '');
  4004. var
  4005.     n: integer;
  4006.     one,two,three: boolean;
  4007.  
  4008. begin
  4009.     gethere;
  4010.     if s = '' then begin    { do an ordinary top-level room look }
  4011.  
  4012.         if hiding then begin
  4013.             writeln('You can''t get a very good view of the details of the room from where');
  4014.             writeln('you are hiding.');
  4015.             noisehide(67);
  4016.         end else begin
  4017.             print_room;
  4018.             show_exits;
  4019.         end;        { end of what you can't see when you're hiding }
  4020.         show_people;
  4021.         show_group;
  4022.         show_objects;
  4023.     end else begin        { look at a detail in the room }
  4024.         one := look_detail(s);
  4025.         two := look_person(s);
  4026.         do_examine(s,three,TRUE);
  4027.         if not(one or two or three) then
  4028.             writeln('There isn''t anything here by that name to look at.');
  4029.     end;
  4030. end;
  4031.  
  4032.  
  4033. procedure init_exit(dir: integer);
  4034.  
  4035. begin
  4036.     with here.exits[dir] do begin
  4037.         exitdesc := DEFAULT_LINE;
  4038.         fail := DEFAULT_LINE;        { default descriptions }
  4039.         success := 0;            { until they customize }
  4040.         comeout := DEFAULT_LINE;
  4041.         goin := DEFAULT_LINE;
  4042.         closed := DEFAULT_LINE;
  4043.  
  4044.         objreq := 0;        { not a door (yet) }
  4045.         hidden := 0;        { not hidden }
  4046.         reqalias := false;    { don't require alias (i.e. can use
  4047.                       direction of exit North, east, etc. }
  4048.         reqverb := false;
  4049.         autolook := true;
  4050.         alias := '';
  4051.     end;
  4052. end;
  4053.  
  4054.  
  4055.  
  4056. procedure remove_exit(dir: integer);
  4057. var
  4058.     targroom,targslot: integer;
  4059.     hereacc,targacc: boolean;
  4060.  
  4061. begin
  4062.         { Leave residual accepts if player is not the owner of
  4063.           the room that the exit he is deleting is in }
  4064.  
  4065.     getroom;
  4066.     targroom := here.exits[dir].toloc;
  4067.     targslot := here.exits[dir].slot;
  4068.     here.exits[dir].toloc := 0;
  4069.     init_exit(dir);
  4070.  
  4071.     if (here.owner = userid) or (privd) then
  4072.         hereacc := false
  4073.     else
  4074.         hereacc := true;
  4075.  
  4076.     if hereacc then
  4077.         here.exits[dir].kind := 5    { put an "accept" in its place }
  4078.     else
  4079.         here.exits[dir].kind := 0;
  4080.  
  4081.     putroom;
  4082.     log_event(myslot,E_DETACH,dir,0,myname,location);
  4083.  
  4084.     getroom(targroom);
  4085.     here.exits[targslot].toloc := 0;
  4086.  
  4087.     if (here.owner = userid) or (privd) then
  4088.         targacc := false
  4089.     else
  4090.         targacc := true;
  4091.  
  4092.     if targacc then
  4093.         here.exits[targslot].kind := 5    { put an "accept" in its place }
  4094.     else
  4095.         here.exits[targslot].kind := 0;
  4096.  
  4097.     putroom;
  4098.  
  4099.     if targroom <> location then
  4100.         log_event(0,E_DETACH,targslot,0,myname,targroom);
  4101.     writeln('Exit destroyed.');
  4102. end;
  4103.  
  4104.  
  4105. {
  4106. User procedure to unlink a room
  4107. }
  4108. procedure do_unlink(s: string);
  4109. var
  4110.     dir: integer;
  4111.  
  4112. begin
  4113.     gethere;
  4114.     if checkhide then begin
  4115.     if lookup_dir(dir,s) then begin
  4116.         if can_alter(dir) then begin
  4117.             if here.exits[dir].toloc = 0 then
  4118.                 writeln('There is no exit there to unlink.')
  4119.             else
  4120.                 remove_exit(dir);
  4121.         end else
  4122.             writeln('You are not allowed to remove that exit.');
  4123.     end else
  4124.         writeln('To remove an exit, type UNLINK <direction of exit>.');
  4125.     end;
  4126. end;
  4127.  
  4128.  
  4129.  
  4130. function desc_allowed: boolean;
  4131.  
  4132. begin
  4133.     if (here.owner = userid) or
  4134.        (privd) then
  4135.         desc_allowed := true
  4136.     else begin
  4137.         writeln('Sorry, you are not allowed to alter the descriptions in this room.');
  4138.         desc_allowed := false;
  4139.     end;
  4140. end;
  4141.  
  4142.  
  4143.  
  4144. function slead(s: string):string;
  4145. var
  4146.     i: integer;
  4147.     going: boolean;
  4148.  
  4149. begin 
  4150.     if length(s) = 0 then
  4151.         slead := ''
  4152.     else begin
  4153.         i := 1;
  4154.         going := true;
  4155.         while going do begin
  4156.             if i > length(s) then
  4157.                 going := false
  4158.             else if (s[i]=' ') or (s[i]=chr(9)) then
  4159.                 i := i + 1
  4160.             else
  4161.                 going := false;
  4162.         end;
  4163.  
  4164.         if i > length(s) then
  4165.             slead := ''
  4166.         else
  4167.             slead := substr(s,i,length(s)+1-i);
  4168.     end;
  4169. end;
  4170.  
  4171.  
  4172. function bite(var s: string): string;
  4173. var
  4174.     i: integer;
  4175.  
  4176. begin
  4177.     if length(s) = 0 then
  4178.         bite := ''
  4179.     else begin
  4180.         i := index(s,' ');
  4181.         if i = 0 then begin
  4182.             bite := s;
  4183.             s := '';
  4184.         end else begin
  4185.             bite := substr(s,1,i-1);
  4186.             s := slead(substr(s,i+1,length(s)-i));
  4187.         end;
  4188.     end;
  4189. end;
  4190.  
  4191. procedure edit_help;
  4192.  
  4193. begin
  4194.     writeln;
  4195.     writeln('A    Append text to end');
  4196.     writeln('C    Check text for correct length with parameter substitution (#)');
  4197.     writeln('D #    Delete line #');
  4198.     writeln('E    Exit & save changes');
  4199.     writeln('I #    Insert lines before line #');
  4200.     writeln('P    Print out description');
  4201.     writeln('Q    Quit: THROWS AWAY CHANGES');
  4202.     writeln('R #    Replace text of line #');
  4203.     writeln('Z    Zap all text');
  4204.     writeln('@    Throw away text & exit with the default description');
  4205.     writeln('?    This list');
  4206.     writeln;
  4207. end;
  4208.  
  4209. procedure edit_replace(n: integer);
  4210. var
  4211.     prompt: string;
  4212.     s: string;
  4213.  
  4214. begin
  4215.     if (n > heredsc.desclen) or (n < 1) then
  4216.         writeln('-- Bad line number')
  4217.     else begin
  4218.         writev(prompt,n:2,': ');
  4219.         grab_line(prompt,s);
  4220.         if s <> '**' then
  4221.             heredsc.lines[n] := s;
  4222.     end;
  4223. end;
  4224.  
  4225. procedure edit_insert(n: integer);
  4226. var
  4227.     i: integer;
  4228.  
  4229. begin
  4230.     if heredsc.desclen = descmax then
  4231.         writeln('You have already used all ',descmax:1,' lines of text.')
  4232.     else if (n < 1) or (n > heredsc.desclen) then begin
  4233.         writeln('Invalid line #; valid lines are between 1 and ',heredsc.desclen:1);
  4234.         writeln('Use A (add) to add text to the end of your description.');
  4235.     end else begin
  4236.         for i := heredsc.desclen+1 downto n + 1 do
  4237.             heredsc.lines[i] := heredsc.lines[i-1];
  4238.         heredsc.desclen := heredsc.desclen + 1;
  4239.         heredsc.lines[n] := '';
  4240.     end;
  4241. end;
  4242.  
  4243. procedure edit_doinsert(n: integer);
  4244. var
  4245.     s: string;
  4246.     prompt: string;
  4247.  
  4248. begin
  4249.     if heredsc.desclen = descmax then
  4250.         writeln('You have already used all ',descmax:1,' lines of text.')
  4251.     else if (n < 1) or (n > heredsc.desclen) then begin
  4252.         writeln('Invalid line #; valid lines are between 1 and ',heredsc.desclen:1);
  4253.         writeln('Use A (add) to add text to the end of your description.');
  4254.     end else repeat
  4255.         writev(prompt,n:1,': ');
  4256.         grab_line(prompt,s);
  4257.         if s <> '**' then begin
  4258.             edit_insert(n);        { put the blank line in }
  4259.             heredsc.lines[n] := s;    { copy this line onto it }
  4260.             n := n + 1;
  4261.         end;
  4262.     until (heredsc.desclen = descmax) or (s = '**');
  4263. end;
  4264.  
  4265. procedure edit_show;
  4266. var
  4267.     i: integer;
  4268.  
  4269. begin
  4270.     writeln;
  4271.     if heredsc.desclen = 0 then
  4272.         writeln('[no text]')
  4273.     else begin
  4274.         i := 1;
  4275.         while i <= heredsc.desclen do begin
  4276.             writeln(i:2,': ',heredsc.lines[i]);
  4277.             i := i + 1;
  4278.         end;
  4279.     end;
  4280. end;
  4281.  
  4282. procedure edit_append;
  4283. var
  4284.     prompt,s: string;
  4285.     stilladding: boolean;
  4286.  
  4287. begin
  4288.     if heredsc.desclen = descmax then
  4289.         writeln('You have already used all ',descmax:1,' lines of text.')
  4290.     else begin
  4291.         stilladding := true;
  4292.         writeln('Enter text.  Terminate with ** at the beginning of a line.');
  4293.         writeln('You have ',descmax:1,' lines maximum.');
  4294.         writeln;
  4295.         while (heredsc.desclen < descmax) and (stilladding) do begin
  4296.             writev(prompt,heredsc.desclen+1:2,': ');
  4297.             grab_line(prompt,s);
  4298.             if s = '**' then
  4299.                 stilladding := false
  4300.             else begin
  4301.                 heredsc.desclen := heredsc.desclen + 1;
  4302.                 heredsc.lines[heredsc.desclen] := s;
  4303.             end;
  4304.         end;
  4305.     end;
  4306. end;
  4307.  
  4308. procedure edit_delete(n: integer);
  4309. var
  4310.     i: integer;
  4311.  
  4312. begin
  4313.     if heredsc.desclen = 0 then
  4314.         writeln('-- No lines to delete')
  4315.     else if (n > heredsc.desclen) or (n < 1) then
  4316.         writeln('-- Bad line number')
  4317.     else if (n = 1) and (heredsc.desclen = 1) then
  4318.         heredsc.desclen := 0
  4319.     else begin
  4320.         for i := n to heredsc.desclen-1 do
  4321.             heredsc.lines[i] := heredsc.lines[i + 1];
  4322.         heredsc.desclen := heredsc.desclen - 1;
  4323.     end;
  4324. end;
  4325.  
  4326.  
  4327. procedure check_subst;
  4328. var
  4329.     i: integer;
  4330.  
  4331. begin
  4332.     if heredsc.desclen > 0 then begin
  4333.         for i := 1 to heredsc.desclen do
  4334.             if (index(heredsc.lines[i],'#') > 0) and
  4335.                (length(heredsc.lines[i]) > 59) then
  4336.                 writeln('Warning: line ',i:1,' is too long for correct parameter substitution.');
  4337.     end;
  4338. end;
  4339.  
  4340.  
  4341. function edit_desc(var dsc: integer):boolean;
  4342. var
  4343.     cmd: char;
  4344.     s: string;
  4345.     done: boolean;
  4346.     n: integer;
  4347.  
  4348. begin
  4349.     if dsc = DEFAULT_LINE then begin
  4350.         heredsc.desclen := 0;
  4351.     end else if dsc > 0 then begin
  4352.         getblock(dsc);
  4353.         freeblock;
  4354.         heredsc := block;
  4355.     end else if dsc < 0 then begin
  4356.         n := (- dsc);
  4357.         getline(n);
  4358.         freeline;
  4359.         heredsc.lines[1] := oneliner.theline;
  4360.         heredsc.desclen := 1;
  4361.     end else begin
  4362.         heredsc.desclen := 0;
  4363.     end;
  4364.  
  4365.     edit_desc := true;
  4366.     done := false;
  4367.     if heredsc.desclen = 0 then
  4368.         edit_append;
  4369.     repeat
  4370.         writeln;
  4371.         repeat
  4372.             grab_line('* ',s);
  4373.             s := slead(s);
  4374.         until length(s) > 0;
  4375.         s := lowcase(s);
  4376.         cmd := s[1];
  4377.  
  4378.         if length(s)>1 then begin
  4379.             n := number(slead(substr(s,2,length(s)-1)))
  4380.         end else
  4381.             n := 0;
  4382.  
  4383.         case cmd of
  4384.             'h','?': edit_help;
  4385.             'a': edit_append;
  4386.             'z': heredsc.desclen := 0;
  4387.             'c': check_subst;
  4388.             'p','l','t': edit_show;
  4389.             'd': edit_delete(n);
  4390.             'e': begin
  4391.                 check_subst;
  4392.                 if debug then
  4393.                     writeln('edit_desc: dsc is ',dsc:1);
  4394.  
  4395.  
  4396. { what I do here may require some explanation:
  4397.  
  4398.     dsc is a pointer to some text structure:
  4399.         dsc = 0 :  no text
  4400.         dsc > 0 :  dsc refers to a description block (descmax lines)
  4401.         dsc < 0 :  dsc refers to a description "one liner".  abs(dsc)
  4402.                is the actual pointer
  4403.  
  4404.     If there are no lines of text to be written out (heredsc.desclen = 0)
  4405.     then we deallocate whatever dsc is when edit_desc was invoked, if
  4406.     it was pointing to something;
  4407.  
  4408.     if there is one line of text to be written out, allocate a one liner
  4409.     record, assign the string to it, and return dsc as negative;
  4410.  
  4411.     if there is mmore than one line of text, allocate a description block,
  4412.     store the lines in it, and return dsc as positive.
  4413.  
  4414.     In all cases if there was already a record allocated to dsc then
  4415.     use it and don't reallocate a new record.
  4416. }
  4417.  
  4418. { kill the default }        if (heredsc.desclen > 0) and
  4419. { if we're gonna put real }        (dsc = DEFAULT_LINE) then
  4420. { texty in here }                dsc := 0;
  4421.  
  4422. { no lines, delete existing }    if heredsc.desclen = 0 then
  4423. { desc, if any }            delete_block(dsc)
  4424.                 else if heredsc.desclen = 1 then begin
  4425.                     if (dsc = 0) then begin
  4426.                         if alloc_line(dsc) then;
  4427.                         dsc := (- dsc);
  4428.                     end else if dsc > 0 then begin
  4429.                         delete_block(dsc);
  4430.                         if alloc_line(dsc) then;
  4431.                         dsc := (- dsc);
  4432.                     end;
  4433.  
  4434.                     if dsc < 0 then begin
  4435.                         getline( abs(dsc) );
  4436.                         oneliner.theline := heredsc.lines[1];
  4437.                         putline;
  4438.                     end;
  4439. { more than 1 lines }        end else begin
  4440.                     if dsc = 0 then begin
  4441.                         if alloc_block(dsc) then;
  4442.                     end else if dsc < 0 then begin
  4443.                         delete_line(dsc);
  4444.                         if alloc_block(dsc) then;
  4445.                     end;
  4446.  
  4447.                     if dsc > 0 then begin
  4448.                         getblock(dsc);
  4449.                         block := heredsc;
  4450. { This is a fudge }                block.descrinum := dsc;
  4451.                         putblock;
  4452.                     end;
  4453.                 end;
  4454.                 done := true;
  4455.                  end;
  4456.             'r': edit_replace(n);
  4457.             '@': begin
  4458.                 delete_block(dsc);
  4459.                 dsc := DEFAULT_LINE;
  4460.                 done := true;
  4461.                  end;
  4462.             'i': edit_doinsert(n);
  4463.             'q': begin
  4464.                 grab_line('Throw away changes, are you sure? ',s);
  4465.                 s := lowcase(s);
  4466.                 if (s = 'y') or (s = 'yes') then begin
  4467.                     done := true;
  4468.                     edit_desc := false; { signal caller not to save }
  4469.                 end;
  4470.                  end;
  4471.             otherwise writeln('-- Invalid command, type ? for a list.');
  4472.         end;
  4473.     until done;
  4474. end;
  4475.  
  4476.  
  4477.  
  4478.  
  4479. function alloc_detail(var n: integer;s: string): boolean;
  4480. var
  4481.     found: boolean;
  4482.  
  4483. begin
  4484.     n := 1;
  4485.     found := false;
  4486.     while (n <= maxdetail) and (not found) do begin
  4487.         if here.detaildesc[n] = 0 then
  4488.             found := true
  4489.         else
  4490.             n := n + 1;
  4491.     end;
  4492.     alloc_detail := found;
  4493.     if not(found) then
  4494.         n := 0
  4495.     else begin
  4496.         getroom;
  4497.         here.detail[n] := lowcase(s);
  4498.         putroom;
  4499.     end;
  4500. end;
  4501.  
  4502.  
  4503. {
  4504. User describe procedure.  If no s then describe the room
  4505.  
  4506. Known problem: if two people edit the description to the same room one of their
  4507.     description blocks could be lost.
  4508. This is unlikely to happen unless the Monster Manager tries to edit a
  4509. description while the room's owner is also editing it.
  4510. }
  4511. procedure do_describe(s: string);
  4512. var
  4513.     i: integer;
  4514.     newdsc: integer;
  4515.  
  4516. begin
  4517.     gethere;
  4518.     if checkhide then begin
  4519.     if s = '' then begin { describe this room }
  4520.         if desc_allowed then begin
  4521.             log_action(desc,0);
  4522.             writeln('[ Editing the primary room description ]');
  4523.             newdsc := here.primary;
  4524.             if edit_desc(newdsc) then begin
  4525.                 getroom;
  4526.                 here.primary := newdsc;
  4527.                 putroom;
  4528.             end;
  4529.             log_event(myslot,E_EDITDONE,0,0);
  4530.         end;
  4531.     end else begin{ describe a detail of this room }
  4532.         if length(s) > veryshortlen then
  4533.             writeln('Your detail keyword can only be ',veryshortlen:1,' characters.')
  4534.         else if desc_allowed then begin
  4535.             if not(lookup_detail(i,s)) then
  4536.             if not(alloc_detail(i,s)) then begin
  4537.                 writeln('You have used all ',maxdetail:1,' details.');
  4538.                 writeln('To delete a detail, DESCRIBE <the detail> and delete all the text.');
  4539.             end;
  4540.             if i <> 0 then begin
  4541.                 log_action(e_detail,0);
  4542.                 writeln('[ Editing detail "',here.detail[i],'" of this room ]');
  4543.                 newdsc := here.detaildesc[i];
  4544.                 if edit_desc(newdsc) then begin
  4545.                     getroom;
  4546.                     here.detaildesc[i] := newdsc;
  4547.                     putroom;
  4548.                 end;
  4549.                 log_event(myslot,E_DONEDET,0,0);
  4550.             end;
  4551.         end;
  4552.     end;
  4553. {    clear_command;    }
  4554.     end;
  4555. end;
  4556.  
  4557.  
  4558.  
  4559.  
  4560. procedure del_room(n: integer);
  4561. var
  4562.     i: integer;
  4563.  
  4564. begin
  4565.     getnam;
  4566.     nam.idents[n] := '';    { blank out name }
  4567.     putnam;
  4568.  
  4569.     getown;
  4570.     own.idents[n] := '';    { blank out owner }
  4571.     putown;
  4572.  
  4573.     getroom(n);
  4574.     for i := 1 to maxexit do begin
  4575.         with here.exits[i] do begin
  4576.             delete_line(exitdesc);
  4577.             delete_line(fail);
  4578.             delete_line(success);
  4579.             delete_line(comeout);
  4580.             delete_line(goin);
  4581.         end;
  4582.     end;
  4583.     delete_block(here.primary);
  4584.     delete_block(here.secondary);
  4585.     putroom;
  4586.     delete_room(n);    { return room to free list }
  4587. end;
  4588.  
  4589.  
  4590.  
  4591. procedure createroom(s: string);    { create a room with name s }
  4592. var
  4593.     roomno: integer;
  4594.     dummy: integer;
  4595.     i:integer;
  4596.     rand_accept: integer;
  4597.  
  4598. begin
  4599.     if length(s) = 0 then begin
  4600.         writeln('Please specify the name of the room you wish to create as a parameter to FORM.');
  4601.     end else if length(s) > shortlen then begin
  4602.         writeln('Please limit your room name to a maximum of ',shortlen:1,' characters.');
  4603.     end else if exact_room(dummy,s) then begin
  4604.         writeln('That room name has already been used.  Please give a unique room name.');
  4605.     end else if alloc_room(roomno) then begin
  4606.         log_action(form,0);
  4607.  
  4608.         getnam;
  4609.         nam.idents[roomno] := lowcase(s);    { assign room name }
  4610.         putnam;                    { case insensitivity }
  4611.  
  4612.         getown;
  4613.         own.idents[roomno] := userid;    { assign room owner }
  4614.         putown;
  4615.  
  4616.         getroom(roomno);
  4617.  
  4618.         here.primary := 0;
  4619.         here.secondary := 0;
  4620.         here.which := 0;    { print primary desc only by default }
  4621.         here.magicobj := 0;
  4622.  
  4623.         here.owner := userid;    { owner and name are stored here too }
  4624.         here.nicename := s;
  4625.         here.nameprint := 1;    { You're in ... }
  4626.         here.objdrop := 0;    { objects dropped stay here }
  4627.         here.objdesc := 0;    { nothing printed when they drop }
  4628.         here.magicobj := 0;    { no magic object default }
  4629.         here.trapto := 0;    { no trapdoor }
  4630.         here.trapchance := 0;    { no chance }
  4631.         here.rndmsg := DEFAULT_LINE;    { bland noises message }
  4632.         here.pile := 0;
  4633.         here.grploc1 := 0;
  4634.         here.grploc2 := 0;
  4635.         here.grpnam1 := '';
  4636.         here.grpnam2 := '';
  4637.  
  4638.         here.effects := 0;
  4639.         here.parm := 0;
  4640.  
  4641.         here.xmsg2 := 0;
  4642.         here.exp2 := 0;
  4643.         here.exp3 := 0;
  4644.         here.exp4 := 0;
  4645.         here.exitfail := DEFAULT_LINE;
  4646.         here.ofail := DEFAULT_LINE;
  4647.  
  4648.         for i := 1 to maxpeople do
  4649.             here.people[i].kind := 0;
  4650.  
  4651.         for i := 1 to maxpeople do
  4652.             here.people[i].name := '';
  4653.  
  4654.         for i := 1 to maxobjs do
  4655.             here.objs[i] := 0;
  4656.  
  4657.         for i := 1 to maxdetail do
  4658.             here.detail[i] := '';
  4659.         for i := 1 to maxdetail do
  4660.             here.detaildesc[i] := 0;
  4661.  
  4662.         for i := 1 to maxobjs do
  4663.             here.objhide[i] := 0;
  4664.  
  4665.         for i := 1 to maxexit do
  4666.             with here.exits[i] do begin
  4667.                 toloc := 0;
  4668.                 kind := 0;
  4669.                 slot := 0;
  4670.                 exitdesc := DEFAULT_LINE;
  4671.                 fail := DEFAULT_LINE;
  4672.                 success := 0;    { no success desc by default }
  4673.                 goin := DEFAULT_LINE;
  4674.                 comeout := DEFAULT_LINE;
  4675.                 closed := DEFAULT_LINE;
  4676.  
  4677.                 objreq := 0;
  4678.                 hidden := 0;
  4679.                 alias := '';
  4680.  
  4681.                 reqverb := false;
  4682.                 reqalias := false;
  4683.                 autolook := true;
  4684.             end;
  4685.         
  4686. {        here.exits := zero;    }
  4687.  
  4688.                 { random accept for this room }
  4689.         rand_accept := 1 + (rnd100 mod 6);
  4690.         here.exits[rand_accept].kind := 5;
  4691.  
  4692.         putroom;
  4693.     end;
  4694. end;
  4695.  
  4696.  
  4697.  
  4698. procedure show_help;
  4699. var
  4700.     i: integer;
  4701.     s: string;
  4702.  
  4703. begin
  4704.     writeln;
  4705.     writeln('Accept/Refuse #  Allow others to Link an exit here at direction # | Undo Accept');
  4706.     writeln('Brief            Toggle printing of room descriptions');
  4707.     writeln('Customize [#]    Customize this room | Customize exit # | Customize object #');
  4708.     writeln('Describe [#]     Describe this room | Describe a feature (#) in detail');
  4709.     writeln('Destroy #        Destroy an instance of object # (you must be holding it)');
  4710.     writeln('Duplicate #      Make a duplicate of an already-created object.');
  4711.     writeln('Form/Zap #       Form a new room with name # | Destroy room named #');
  4712.     writeln('Get/Drop #       Get/Drop an object');
  4713.     writeln('#,Go #           Go towards # (Some: N/North S/South E/East W/West U/Up D/Down)');
  4714.     writeln('Health           Show how healthy you are');
  4715.     writeln('Hide/Reveal [#]  Hide/Reveal yoursef | Hide object (#)');
  4716.     writeln('I,Inventory      See what you or someone else is carrying');
  4717.     writeln('Link/Unlink #    Link/Unlink this room to/from another via exit at direction #');
  4718.     writeln('Look,L [#]       Look here | Look at something or someone (#) closely');
  4719.     writeln('Make #           Make a new object named #');
  4720.     writeln('Name #           Set your game name to #');
  4721.     writeln('Players          List people who have played Monster');
  4722.     writeln('Punch #          Punch person #');
  4723.     writeln('Quit             Leave the game');
  4724.     writeln('Relink           Move an exit');
  4725.     writeln;
  4726.     grab_line('-more-',s);
  4727.     writeln;
  4728.     writeln('Rooms            Show information about rooms you have made');
  4729.     writeln('Say, '' (quote)   Say line of text following command to others in the room');
  4730.     writeln('Search           Look around the room for anything hidden');
  4731.     writeln('Self #           Edit a description of yourself | View #''s self-description');
  4732.     writeln('Show #           Show option # (type SHOW ? for a list)');
  4733.     writeln('Unmake #         Remove the form definition of object #');
  4734.     writeln('Use #            Use object #');
  4735.     writeln('Wear #           Wear the object #');
  4736.     writeln('Wield #          Wield the weapon #;  you must be holding it first');
  4737.     writeln('Whisper #        Whisper something (prompted for) to person #');
  4738.     writeln('Who              List of people playing Monster now');
  4739.     writeln('Whois #          What is a player''s username');
  4740.     writeln('?,Help           This list');
  4741.     writeln('. (period)       Repeat last command');
  4742.     writeln;
  4743. end;
  4744.  
  4745.  
  4746. function lookup_cmd(s: string):integer;
  4747. var
  4748.     i,        { index for loop }
  4749.     poss,        { a possible match -- only for partial matches }
  4750.     maybe,        { number of possible matches we have: > 2 is ambig. }
  4751.     num        { the definite match }
  4752.         : integer;
  4753.  
  4754.  
  4755. begin
  4756.     s := lowcase(s);
  4757.     i := 1;
  4758.     maybe := 0;
  4759.     num := 0;
  4760.     for i := 1 to numcmds do begin
  4761.         if s = cmds[i] then
  4762.             num := i
  4763.         else if index(cmds[i],s) = 1 then begin
  4764.             maybe := maybe + 1;
  4765.             poss := i;
  4766.         end;
  4767.     end;
  4768.     if num <> 0 then begin
  4769.         lookup_cmd := num;
  4770.     end else if maybe = 1 then begin
  4771.         lookup_cmd := poss;
  4772.     end else if maybe > 1 then
  4773.         lookup_cmd := error    { "Ambiguous" }
  4774.     else
  4775.         lookup_cmd := error;    { "Command not found " }
  4776. end;
  4777.  
  4778.  
  4779. procedure addrooms(n: integer);
  4780. var
  4781.     i: integer;
  4782.  
  4783. begin
  4784.     getindex(I_ROOM);
  4785.     for i := indx.top+1 to indx.top+n do begin
  4786.         locate(roomfile,i);
  4787.         roomfile^.valid := i;
  4788.         roomfile^.locnum := i;
  4789.         roomfile^.primary := 0;
  4790.         roomfile^.secondary := 0;
  4791.         roomfile^.which := 0;
  4792.         put(roomfile);
  4793.     end;
  4794.     indx.top := indx.top + n;
  4795.     putindex;
  4796. end;
  4797.  
  4798.  
  4799.  
  4800. procedure addints(n: integer);
  4801. var
  4802.     i: integer;
  4803.  
  4804. begin
  4805.     getindex(I_INT);
  4806.     for i := indx.top+1 to indx.top+n do begin
  4807.         locate(intfile,i);
  4808.         intfile^.intnum := i;
  4809.         put(intfile);
  4810.     end;
  4811.     indx.top := indx.top + n;
  4812.     putindex;
  4813. end;
  4814.  
  4815.  
  4816.  
  4817. procedure addlines(n: integer);
  4818. var
  4819.     i: integer;
  4820.  
  4821. begin
  4822.     getindex(I_LINE);
  4823.     for i := indx.top+1 to indx.top+n do begin
  4824.         locate(linefile,i);
  4825.         linefile^.linenum := i;
  4826.         put(linefile);
  4827.     end;
  4828.     indx.top := indx.top + n;
  4829.     putindex;
  4830. end;
  4831.  
  4832. procedure addblocks(n: integer);
  4833. var
  4834.     i: integer;
  4835.  
  4836. begin
  4837.     getindex(I_BLOCK);
  4838.     for i := indx.top+1 to indx.top+n do begin
  4839.         locate(descfile,i);
  4840.         descfile^.descrinum := i;
  4841.         put(descfile);
  4842.     end;
  4843.     indx.top := indx.top + n;
  4844.     putindex;
  4845. end;
  4846.  
  4847.  
  4848. procedure addobjects(n: integer);
  4849. var
  4850.     i: integer;
  4851.  
  4852. begin
  4853.     getindex(I_OBJECT);
  4854.     for i := indx.top+1 to indx.top+n do begin
  4855.         locate(objfile,i);
  4856.         objfile^.objnum := i;
  4857.         put(objfile);
  4858.     end;
  4859.     indx.top := indx.top + n;
  4860.     putindex;
  4861. end;
  4862.  
  4863.  
  4864. procedure dist_list;
  4865. var
  4866.     i,j: integer;
  4867.     f: text;
  4868.     where_they_are: intrec;
  4869.  
  4870. begin
  4871.     writeln('Writing distribution list . . .');
  4872.     open(f,'monsters.dis',history := new);
  4873.     rewrite(f);
  4874.  
  4875.     getindex(I_PLAYER);    { Rec of valid player log records  }
  4876.     freeindex;        { False if a valid player log }
  4877.  
  4878.     getuser;        { Corresponding userids of players }
  4879.     freeuser;
  4880.  
  4881.     getpers;        { Personal names of players }
  4882.     freepers;
  4883.  
  4884.     getdate;        { date of last play }
  4885.     freedate;
  4886.  
  4887.     if privd then begin
  4888.         getint(N_LOCATION);
  4889.         freeint;
  4890.         where_they_are := anint;
  4891.  
  4892.         getnam;
  4893.         freenam;
  4894.     end;
  4895.  
  4896.     for i := 1 to maxplayers do begin
  4897.         if not(indx.free[i]) then begin
  4898.             write(f,user.idents[i]);
  4899.             for j := length(user.idents[i]) to 15 do
  4900.                 write(f,' ');
  4901.             write(f,'! ',pers.idents[i]);
  4902.             for j := length(pers.idents[i]) to 21 do
  4903.                 write(f,' ');
  4904.  
  4905.             write(f,adate.idents[i]);
  4906.                 if length(adate.idents[i]) < 19 then
  4907.                     for j := length(adate.idents[i]) to 18 do
  4908.                         write(f,' ');
  4909.             if anint.int[i] <> 0 then
  4910.                 write(f,' * ')
  4911.             else
  4912.                 write(f,'   ');
  4913.  
  4914.             if privd then begin
  4915.                 write(f,nam.idents[ where_they_are.int[i] ]);
  4916.             end;
  4917.             writeln(f);
  4918.  
  4919.         end;
  4920.     end;
  4921.     writeln('Done.');
  4922. end;
  4923.  
  4924.  
  4925. procedure system_view;
  4926. var
  4927.     used,free,total: integer;
  4928.  
  4929. begin
  4930.     writeln;
  4931.     getindex(I_BLOCK);
  4932.     freeindex;
  4933.     used := indx.inuse;
  4934.     total := indx.top;
  4935.     free := total - used;
  4936.  
  4937.     writeln('               used   free   total');
  4938.     writeln('Block file   ',used:5,'  ',free:5,'   ',total:5);
  4939.  
  4940.     getindex(I_LINE);
  4941.     freeindex;
  4942.     used := indx.inuse;
  4943.     total := indx.top;
  4944.     free := total - used;
  4945.     writeln('Line file    ',used:5,'  ',free:5,'   ',total:5);
  4946.  
  4947.     getindex(I_ROOM);
  4948.     freeindex;
  4949.     used := indx.inuse;
  4950.     total := indx.top;
  4951.     free := total - used;
  4952.     writeln('Room file    ',used:5,'  ',free:5,'   ',total:5);
  4953.  
  4954.     getindex(I_OBJECT);
  4955.     freeindex;
  4956.     used := indx.inuse;
  4957.     total := indx.top;
  4958.     free := total - used;
  4959.     writeln('Object file  ',used:5,'  ',free:5,'   ',total:5);
  4960.  
  4961.     getindex(I_INT);
  4962.     freeindex;
  4963.     used := indx.inuse;
  4964.     total := indx.top;
  4965.     free := total - used;
  4966.     writeln('Integer file ',used:5,'  ',free:5,'   ',total:5);
  4967.  
  4968.     writeln;
  4969. end;
  4970.  
  4971.  
  4972. { remove a user from the log records (does not handle ownership) }
  4973.  
  4974. procedure kill_user(s:string);
  4975. var
  4976.     n: integer;
  4977.  
  4978. begin
  4979.     if length(s) = 0 then
  4980.         writeln('No user specified')
  4981.     else begin
  4982.         if lookup_user(n,s) then begin
  4983.             getindex(I_ASLEEP);
  4984.             freeindex;
  4985.             if indx.free[n] then begin
  4986.                 delete_log(n);
  4987.                 writeln('Player deleted.');
  4988.             end else
  4989.                 writeln('That person is playing now.');
  4990.         end else
  4991.             writeln('No such userid found in log information.');
  4992.     end;
  4993. end;
  4994.  
  4995.  
  4996. { disown everything a player owns }
  4997.  
  4998. procedure disown_user(s:string);
  4999. var
  5000.     n: integer;
  5001.     i: integer;
  5002.     tmp: string;
  5003.     theuser: string;
  5004.  
  5005. begin
  5006.     if length(s) > 0 then begin
  5007.         if debug then
  5008.             writeln('calling lookup_user with ',s);
  5009.         if not lookup_user(n,s) then
  5010.             writeln('User not in log info, attempting to disown anyway.');
  5011.  
  5012.         theuser := user.idents[n];
  5013.  
  5014.         { first disown all their rooms }
  5015.  
  5016.         getown;
  5017.         freeown;
  5018.         for i := 1 to maxroom do
  5019.             if own.idents[i] = theuser then begin
  5020.                 getown;
  5021.                 own.idents[i] := '*';
  5022.                 putown;
  5023.  
  5024.                 getroom(i);
  5025.                 tmp := here.nicename;
  5026.                 here.owner := '*';
  5027.                 putroom;
  5028.  
  5029.                 writeln('Disowned room ',tmp);
  5030.             end;
  5031.         writeln;
  5032.  
  5033.         getobjown;
  5034.         freeobjown;
  5035.         getobjnam;
  5036.         freeobjnam;
  5037.         for i := 1 to maxroom do
  5038.             if objown.idents[i] = theuser then begin
  5039.                 getobjown;
  5040.                 objown.idents[i] := '*';
  5041.                 putobjown;
  5042.  
  5043.                 tmp := objnam.idents[i];
  5044.                 writeln('Disowned object ',tmp);
  5045.             end;
  5046.     end else
  5047.         writeln('No user specified.');
  5048. end;
  5049.  
  5050. procedure move_asleep;
  5051. var
  5052.     pname,rname:string;    { player & room names }
  5053.     newroom,n: integer;    { room number & player slot number }
  5054.  
  5055. begin
  5056.     grab_line('Player name? ',pname);
  5057.     grab_line('Room name?   ',rname);
  5058.     if lookup_user(n,pname) then begin
  5059.         if lookup_room(newroom,rname) then begin
  5060.             getindex(I_ASLEEP);
  5061.             freeindex;
  5062.             if indx.free[n] then begin
  5063.                 getint(N_LOCATION);
  5064.                 anint.int[n] := newroom;
  5065.                 putint;
  5066.                 writeln('Player moved.');
  5067.             end else
  5068.                 writeln('That player is not asleep.');
  5069.         end else
  5070.             writeln('No such room found.');
  5071.     end else
  5072.         writeln('User not found.');
  5073. end;
  5074.  
  5075.  
  5076. procedure system_help;
  5077.  
  5078. begin
  5079.     writeln;
  5080.     writeln('B    Add description blocks');
  5081.     writeln('D    Disown <user>');
  5082.     writeln('E    Exit (same as quit)');
  5083.     writeln('I    Add Integer records');
  5084.     writeln('K    Kill <user>');
  5085.     writeln('L    Add one liner records');
  5086.     writeln('M    Move a player who is asleep (not playing now)');
  5087.     writeln('O    Add object records');
  5088.     writeln('P    Write a distribution list of players');
  5089.     writeln('Q    Quit (same as exit)');
  5090.     writeln('R    Add rooms');
  5091.     writeln('V    View current sizes/usage');
  5092.     writeln('?    This list');
  5093.     writeln;
  5094. end;
  5095.  
  5096.  
  5097. { *************** FIX_STUFF ******************** }
  5098.  
  5099. procedure fix_stuff;
  5100.  
  5101. begin
  5102. end;
  5103.  
  5104.  
  5105. procedure do_system(s: string);
  5106. var
  5107.     prompt: string;
  5108.     done: boolean;
  5109.     cmd: char;
  5110.     n: integer;
  5111.     p: string;
  5112.  
  5113. begin
  5114.     if privd then begin
  5115.         log_action(c_system,0);
  5116.         prompt := 'System> ';
  5117.         done := false;
  5118.         repeat
  5119.             repeat
  5120.                 grab_line(prompt,s);
  5121.                 s := slead(s);
  5122.             until length(s) > 0;
  5123.             s := lowcase(s);
  5124.             cmd := s[1];
  5125.  
  5126.             n := 0;
  5127.             p := '';
  5128.             if length(s) > 1 then begin
  5129.                 p := slead( substr(s,2,length(s)-1) );
  5130.                 n := number(p)
  5131.             end;
  5132.             if debug then begin
  5133.                 writeln('p = ',p);
  5134.             end;
  5135.  
  5136.             case cmd of
  5137.                 'h','?': system_help;
  5138.                 '1': fix_stuff;
  5139. {remove a user}            'k': kill_user(p);
  5140. {disown}            'd': disown_user(p);
  5141. {dist list of players}        'p': dist_list;
  5142. {move where user will wakeup}    'm': move_asleep;
  5143. {add rooms}            'r': begin
  5144.                     if n > 0 then begin
  5145.                         addrooms(n);
  5146.                     end else
  5147.                         writeln('To add rooms, say R <# to add>');
  5148.                      end;
  5149. {add ints}            'i': begin
  5150.                     if n > 0 then begin
  5151.                         addints(n);
  5152.                     end else
  5153.                         writeln('To add integers, say I <# to add>');
  5154.                      end;
  5155. {add description blocks}    'b': begin
  5156.                     if n > 0 then begin
  5157.                         addblocks(n);
  5158.                     end else
  5159.                         writeln('To add description blocks, say B <# to add>');
  5160.                      end;
  5161. {add objects}            'o': begin
  5162.                     if n > 0 then begin
  5163.                         addobjects(n);
  5164.                     end else
  5165.                         writeln('To add object records, say O <# to add>');
  5166.                      end;
  5167. {add one-liners}        'l': begin
  5168.                     if n > 0 then begin
  5169.                         addlines(n);
  5170.                     end else
  5171.                         writeln('To add one liner records, say L <# to add>');
  5172.                      end;
  5173. {view current stats}        'v': begin
  5174.                     system_view;
  5175.                      end;
  5176. {quit}                'q','e': done := true;
  5177.             otherwise writeln('-- bad command, type ? for a list.');
  5178.             end;
  5179.         until done;
  5180.         log_event(myslot,E_SYSDONE,0,0);
  5181.     end else
  5182.         writeln('Only the Monster Manger may enter system maintenance mode.');
  5183. end;
  5184.  
  5185.  
  5186. procedure do_version(s: string);
  5187.  
  5188. begin
  5189.     writeln('Monster, a multiplayer adventure game where the players create the world');
  5190.     writeln('and make the rules.');
  5191.     writeln;
  5192.     writeln('Written by Rich Skrenta at Northwestern University, 1988.');
  5193. end;
  5194.  
  5195.  
  5196. procedure rebuild_system;
  5197. var
  5198.     i,j: integer;
  5199.  
  5200. begin
  5201.     writeln('Creating index file 1-6');
  5202.     for i := 1 to 7 do begin
  5203.             { 1 is blocklist
  5204.               2 is linelist
  5205.               3 is roomlist
  5206.               4 is playeralloc
  5207.               5 is player awake (playing game)
  5208.               6 are objects
  5209.               7 is intfile }
  5210.  
  5211.         locate(indexfile,i);
  5212.         for j := 1 to maxindex do
  5213.             indexfile^.free[j] := true;
  5214.         indexfile^.indexnum := i;
  5215.         indexfile^.top := 0; { none of each to start }
  5216.         indexfile^.inuse := 0;
  5217.         put(indexfile);
  5218.     end;
  5219.  
  5220.  
  5221.     writeln('Initializing roomfile with 10 rooms');
  5222.     addrooms(10);
  5223.  
  5224.     writeln('Initializing block file with 10 description blocks');
  5225.     addblocks(10);
  5226.  
  5227.     writeln('Initializing line file with 10 lines');
  5228.     addlines(10);
  5229.  
  5230.     writeln('Initializing object file with 10 objects');
  5231.     addobjects(10);
  5232.  
  5233.  
  5234.     writeln('Initializing namfile 1-8');
  5235.     for j := 1 to 8 do begin
  5236.         locate(namfile,j);
  5237.         namfile^.validate := j;
  5238.         namfile^.loctop := 0;
  5239.         for i := 1 to maxroom do begin
  5240.             namfile^.idents[i] := '';
  5241.         end;
  5242.         put(namfile);
  5243.     end;
  5244.  
  5245.     writeln('Initializing eventfile');
  5246.     for i := 1 to numevnts + 1 do begin
  5247.         locate(eventfile,i);
  5248.         eventfile^.validat := i;
  5249.         eventfile^.point := 1;
  5250.         put(eventfile);
  5251.     end;
  5252.  
  5253.     writeln('Initializing intfile');
  5254.     for i := 1 to 6 do begin
  5255.         locate(intfile,i);
  5256.         intfile^.intnum := i;
  5257.         put(intfile);
  5258.     end;
  5259.  
  5260.     getindex(I_INT);
  5261.     for i := 1 to 6 do
  5262.         indx.free[i] := false;
  5263.     indx.top := 6;
  5264.     indx.inuse := 6;
  5265.     putindex;
  5266.  
  5267.     { Player log records should have all their slots initially,
  5268.       they don't have to be allocated because they use namrec
  5269.       and intfile for their storage; they don't have their own
  5270.       file to allocate
  5271.     }
  5272.     getindex(I_PLAYER);
  5273.     indx.top := maxplayers;
  5274.     putindex;
  5275.     getindex(I_ASLEEP);
  5276.     indx.top := maxplayers;
  5277.     putindex;
  5278.  
  5279.     writeln('Creating the Great Hall');
  5280.     createroom('Great Hall');
  5281.     getroom(1);
  5282.     here.owner := '';
  5283.     putroom;
  5284.     getown;
  5285.     own.idents[1] := '';
  5286.     putown;
  5287.  
  5288.     writeln('Creating the Void');
  5289.     createroom('Void');            { loc 2 }
  5290.     writeln('Creating the Pit of Fire');
  5291.     createroom('Pit of Fire');        { loc 3 }
  5292.             { note that these are NOT public locations }
  5293.  
  5294.  
  5295.     writeln('Use the SYSTEM command to view and add capacity to the database');
  5296.     writeln;
  5297. end;
  5298.  
  5299.  
  5300. procedure special(s: string);
  5301.  
  5302. begin
  5303.     if (s = 'rebuild') and (privd) then begin
  5304.         if REBUILD_OK then begin
  5305.             writeln('Do you really want to destroy the entire universe?');
  5306.             readln(s);
  5307.             if length(s) > 0 then
  5308.                 if substr(lowcase(s),1,1) = 'y' then
  5309.                     rebuild_system;
  5310.         end else
  5311.             writeln('REBUILD is disabled; you must recompile.');
  5312.     end else if s = 'version' then begin
  5313.         { Don't take this out please... }
  5314.           writeln('Monster, written by Rich Skrenta at Northwestern University, 1988.');
  5315.     end else if s = 'quit' then
  5316.         done := true;
  5317. end;
  5318.  
  5319.  
  5320. { put an object in this location
  5321.   if returns false, there were no more free object slots here:
  5322.   in other words, the room is too cluttered, and cannot hold any
  5323.   more objects
  5324. }
  5325. function place_obj(n: integer;silent:boolean := false): boolean;
  5326. var
  5327.     found: boolean;
  5328.     i: integer;
  5329.  
  5330. begin
  5331.     if here.objdrop = 0 then
  5332.         getroom
  5333.     else
  5334.         getroom(here.objdrop);
  5335.     i := 1;
  5336.     found := false;
  5337.     while (i <= maxobjs) and (not found) do begin
  5338.         if here.objs[i] = 0 then
  5339.             found := true
  5340.         else
  5341.             i := i + 1;
  5342.     end;
  5343.     place_obj := found;
  5344.     if found then begin
  5345.         here.objs[i] := n;
  5346.         here.objhide[i] := 0;
  5347.         putroom;
  5348.  
  5349.         gethere;
  5350.  
  5351.  
  5352.         { if it bounced somewhere else then tell them }
  5353.  
  5354.         if (here.objdrop <> 0) and (here.objdest <> 0) then
  5355.             log_event(0,E_BOUNCEDIN,here.objdest,n,'',here.objdrop);
  5356.  
  5357.  
  5358.         if not(silent) then begin
  5359.             if here.objdesc <> 0 then
  5360.                 print_subs(here.objdesc,obj_part(n))
  5361.             else
  5362.                 writeln('Dropped.');
  5363.         end;
  5364.     end else
  5365.         freeroom;
  5366. end;
  5367.  
  5368.  
  5369. { remove an object from this room }
  5370. function take_obj(objnum,slot: integer): boolean;
  5371.  
  5372. begin
  5373.     getroom;
  5374.     if here.objs[slot] = objnum then begin
  5375.         here.objs[slot] := 0;
  5376.         here.objhide[slot] := 0;
  5377.         take_obj := true;
  5378.     end else
  5379.         take_obj := false;
  5380.     putroom;
  5381. end;
  5382.  
  5383.  
  5384. function can_hold: boolean;
  5385.  
  5386. begin
  5387.     if find_numhold < maxhold then
  5388.         can_hold := true
  5389.     else
  5390.         can_hold := false;
  5391. end;
  5392.  
  5393.  
  5394. function can_drop: boolean;
  5395.  
  5396. begin
  5397.     if find_numobjs < maxobjs then
  5398.         can_drop := true
  5399.     else
  5400.         can_drop := false;
  5401. end;
  5402.  
  5403.  
  5404. function find_hold(objnum: integer;slot:integer := 0): integer;
  5405. var
  5406.     i: integer;
  5407.  
  5408. begin
  5409.     if slot = 0 then
  5410.         slot := myslot;
  5411.     i := 1;
  5412.     find_hold := 0;
  5413.     while i <= maxhold do begin
  5414.         if here.people[slot].holding[i] = objnum then
  5415.             find_hold := i;
  5416.         i := i + 1;
  5417.     end;
  5418. end;
  5419.  
  5420.  
  5421.  
  5422. { put object number n into the player's inventory; returns false if
  5423.   he's holding too many things to carry another }
  5424.  
  5425. function hold_obj(n: integer): boolean;
  5426. var
  5427.     found: boolean;
  5428.     i: integer;
  5429.  
  5430. begin
  5431.     getroom;
  5432.     i := 1;
  5433.     found := false;
  5434.     while (i <= maxhold) and (not found) do begin
  5435.         if here.people[myslot].holding[i] = 0 then
  5436.             found := true
  5437.         else
  5438.             i := i + 1;
  5439.     end;
  5440.     hold_obj := found;
  5441.     if found then begin
  5442.         here.people[myslot].holding[i] := n;
  5443.         putroom;
  5444.  
  5445.         getobj(n);
  5446.         freeobj;
  5447.         hold_kind[i] := obj.kind;
  5448.     end else
  5449.         freeroom;
  5450. end;
  5451.  
  5452.  
  5453.  
  5454. { remove an object (hold) from the player record, given the slot that
  5455.   the object is being held in }
  5456.  
  5457. procedure drop_obj(slot: integer;pslot: integer := 0);
  5458.  
  5459. begin
  5460.     if pslot = 0 then
  5461.         pslot := myslot;
  5462.     getroom;
  5463.     here.people[pslot].holding[slot] := 0;
  5464.     putroom;
  5465.  
  5466.     hold_kind[slot] := 0;
  5467. end;
  5468.  
  5469.  
  5470.  
  5471. { maybe drop something I'm holding if I'm hit }
  5472.  
  5473. procedure maybe_drop;
  5474. var
  5475.     i: integer;
  5476.     objnum: integer;
  5477.     s: string;
  5478.  
  5479. begin
  5480.     i := 1 + (rnd100 mod maxhold);
  5481.     objnum := here.people[myslot].holding[i];
  5482.  
  5483.     if (objnum <> 0) and (mywield <> objnum) and (mywear <> objnum) then begin
  5484.         { drop something }
  5485.  
  5486.         drop_obj(i);
  5487.         if place_obj(objnum,TRUE) then begin
  5488.             getobjnam;
  5489.             freeobjnam;
  5490.             writeln('The ',objnam.idents[objnum],' has slipped out of your hands.');
  5491.  
  5492.             
  5493.         s := objnam.idents[objnum];
  5494.             log_event(myslot,E_SLIPPED,0,0,s);
  5495.         end else
  5496.             writeln('%error in maybe_drop; unsuccessful place_obj; notify Monster Manager');
  5497.  
  5498.     end;
  5499. end;
  5500.  
  5501.  
  5502.  
  5503. { return TRUE if the player is allowed to program the object n
  5504.   if checkpub is true then obj_owner will return true if the object in
  5505.   question is public }
  5506.  
  5507. function obj_owner(n: integer;checkpub: boolean := FALSE):boolean;
  5508.  
  5509. begin
  5510.     getobjown;
  5511.     freeobjown;
  5512.     if (objown.idents[n] = userid) or (privd) then begin
  5513.         obj_owner := true;
  5514.     end else if (objown.idents[n] = '') and (checkpub) then begin
  5515.         obj_owner := true;
  5516.     end else begin
  5517.         obj_owner := false;
  5518.     end;
  5519. end;
  5520.  
  5521.  
  5522. procedure do_duplicate(s: string);
  5523. var
  5524.     objnum: integer;
  5525.  
  5526. begin
  5527.    if length(s) > 0 then begin
  5528.     if not is_owner(location,TRUE) then begin
  5529.             { only let them make things if they're on their home turf }
  5530.         writeln('You may only create objects when you are in one of your own rooms.');
  5531.     end else begin
  5532.         if lookup_obj(objnum,s) then begin
  5533.             if obj_owner(objnum,TRUE) then begin
  5534.                 if not(place_obj(objnum,TRUE)) then
  5535.                     { put the new object here }
  5536.                     writeln('There isn''t enough room here to make that.')
  5537.                 else begin
  5538. { keep track of how many there }    getobj(objnum);
  5539. { are in existence }            obj.numexist := obj.numexist + 1;
  5540.                     putobj;
  5541.  
  5542.                     log_event(myslot,E_MADEOBJ,0,0,
  5543.                         myname + ' has created an object here.');
  5544.                     writeln('Object created.');
  5545.                 end;
  5546.             end else
  5547.                 writeln('Power to create that object belongs to someone else.');
  5548.         end else
  5549.             writeln('There is no object by that name.');
  5550.     end;
  5551.    end else
  5552.         writeln('To duplicate an object, type DUPLICATE <object name>.');
  5553. end;
  5554.  
  5555.  
  5556. { make an object }
  5557. procedure do_makeobj(s: string);
  5558. var
  5559.     objnum: integer;
  5560.  
  5561. begin
  5562.     gethere;
  5563.     if checkhide then begin
  5564.     if not is_owner(location,TRUE) then begin
  5565.         writeln('You may only create objects when you are in one of your own rooms.');
  5566.     end else if s <> '' then begin
  5567.         if length(s) > shortlen then
  5568.             writeln('Please limit your object names to ',shortlen:1,' characters.')
  5569.         else if exact_obj(objnum,s) then begin    { object already exits }
  5570.             writeln('That object already exits.  If you would like to make another copy of it,');
  5571.             writeln('use the DUPLICATE command.');
  5572.         end else begin
  5573.             if debug then
  5574.                 writeln('%beggining to create object');
  5575.             if find_numobjs < maxobjs then begin
  5576.                 if alloc_obj(objnum) then begin
  5577.                     if debug then
  5578.                         writeln('%alloc_obj successful');
  5579.                     getobjnam;
  5580.                     objnam.idents[objnum] := lowcase(s);
  5581.                     putobjnam;
  5582.                     if debug then
  5583.                         writeln('%getobjnam completed');
  5584.                     getobjown;
  5585.                     objown.idents[objnum] := userid;
  5586.                     putobjown;
  5587.                     if debug then
  5588.                         writeln('%getobjown completed');
  5589.  
  5590.                     getobj(objnum);
  5591.                         obj.onum := objnum;
  5592.                         obj.oname := s;    { name of object }
  5593.                         obj.kind := 0; { bland object }
  5594.                         obj.linedesc := DEFAULT_LINE;
  5595.                         obj.actindx := 0;
  5596.                         obj.examine := 0;
  5597.                         obj.numexist := 1;
  5598.                         obj.home := 0;
  5599.                         obj.homedesc := 0;
  5600.  
  5601.                         obj.sticky := false;
  5602.                         obj.getobjreq := 0;
  5603.                         obj.getfail := 0;
  5604.                         obj.getsuccess := DEFAULT_LINE;
  5605.  
  5606.                         obj.useobjreq := 0;
  5607.                         obj.uselocreq := 0;
  5608.                         obj.usefail := DEFAULT_LINE;
  5609.                         obj.usesuccess := DEFAULT_LINE;
  5610.  
  5611.                         obj.usealias := '';
  5612.                         obj.reqalias := false;
  5613.                         obj.reqverb := false;
  5614.  
  5615.             if s[1] in ['a','A','e','E','i','I','o','O','u','U'] then
  5616.                         obj.particle := 2  { an }
  5617.             else
  5618.                         obj.particle := 1; { a }
  5619.  
  5620.                         obj.d1 := 0;
  5621.                         obj.d2 := 0;
  5622.                         obj.exp3 := 0;
  5623.                         obj.exp4 := 0;
  5624.                         obj.exp5 := DEFAULT_LINE;
  5625.                         obj.exp6 := DEFAULT_LINE;
  5626.                     putobj;
  5627.  
  5628.  
  5629.                     if debug then
  5630.                         writeln('putobj completed');
  5631.                 end;
  5632.                     { else: alloc_obj prints errors by itself }
  5633.                 if not(place_obj(objnum,TRUE)) then
  5634.                     { put the new object here }
  5635.                     writeln('%error in makeobj - could not place object; notify the Monster Manager.')
  5636.                 else begin
  5637.                     log_event(myslot,E_MADEOBJ,0,0,
  5638.                         myname + ' has created an object here.');
  5639.                     writeln('Object created.');
  5640.                 end;
  5641.  
  5642.             end else
  5643.                 writeln('This place is too crowded to create any more objects.  Try somewhere else.');
  5644.         end;
  5645.     end else
  5646.         writeln('To create an object, type MAKE <object name>.');
  5647.     end;
  5648. end;
  5649.  
  5650. { remove the type block for an object; all instances of the object must
  5651.   be destroyed first }
  5652.  
  5653. procedure do_unmake(s: string);
  5654. var
  5655.     n: integer;
  5656.     tmp: string;
  5657.  
  5658. begin
  5659.     if not(is_owner(location,TRUE)) then
  5660.         writeln('You must be in one of your own rooms to UNMAKE an object.')
  5661.     else if lookup_obj(n,s) then begin
  5662.         tmp := obj_part(n);
  5663.             { this will do a getobj(n) for us }
  5664.  
  5665.         if obj.numexist = 0 then begin
  5666.             delete_obj(n);
  5667.  
  5668.             log_event(myslot,E_UNMAKE,0,0,tmp);
  5669.             writeln('Object removed.');
  5670.         end else
  5671.             writeln('You must DESTROY all instances of the object first.');
  5672.     end else
  5673.         writeln('There is no object here by that name.');
  5674. end;
  5675.  
  5676.  
  5677. { destroy a copy of an object }
  5678.  
  5679. procedure do_destroy(s: string);
  5680. var
  5681.     slot,n: integer;
  5682.  
  5683. begin
  5684.     if length(s) = 0 then    
  5685.         writeln('To destroy an object you own, type DESTROY <object>.')
  5686.     else if not is_owner(location,TRUE) then
  5687.         writeln('You must be in one of your own rooms to destroy an object.')
  5688.     else if parse_obj(n,s) then begin
  5689.         getobjown;
  5690.         freeobjown;
  5691.         if (objown.idents[n] <> userid) and (objown.idents[n] <> '') and
  5692.            (not privd) then
  5693.             writeln('You must be the owner of an object to destroy it.')
  5694.         else if obj_hold(n) then begin
  5695.             slot := find_hold(n);
  5696.             drop_obj(slot);
  5697.  
  5698.             log_event(myslot,E_DESTROY,0,0,
  5699.                 myname + ' has destroyed ' + obj_part(n) + '.');
  5700.             writeln('Object destroyed.');
  5701.  
  5702.             getobj(n);
  5703.             obj.numexist := obj.numexist - 1;
  5704.             putobj;
  5705.         end else if obj_here(n) then begin
  5706.             slot := find_obj(n);
  5707.             if not take_obj(n,slot) then
  5708.                 writeln('Someone picked it up before you could destroy it.')
  5709.             else begin
  5710.                 log_event(myslot,E_DESTROY,0,0,
  5711.                     myname + ' has destroyed ' + obj_part(n,FALSE) + '.');
  5712.                 writeln('Object destroyed.');
  5713.  
  5714.                 getobj(n);
  5715.                 obj.numexist := obj.numexist - 1;
  5716.                 putobj;
  5717.             end;
  5718.         end else
  5719.             writeln('Such a thing is not here.');
  5720.     end else
  5721.         writeln('No such thing can be seen here.');
  5722. end;
  5723.  
  5724.  
  5725. function links_possible: boolean;
  5726. var
  5727.     i: integer;
  5728.  
  5729. begin
  5730.     gethere;
  5731.     links_possible := false;
  5732.     if is_owner(location,TRUE) then
  5733.         links_possible := true
  5734.     else begin
  5735.         for i := 1 to maxexit do
  5736.             if (here.exits[i].toloc = 0) and (here.exits[i].kind = 5) then
  5737.                 links_possible := true;
  5738.     end;
  5739. end;
  5740.  
  5741.  
  5742.  
  5743. { make a room }
  5744. procedure do_form(s: string);
  5745.  
  5746. begin
  5747.     gethere;
  5748.     if checkhide then begin
  5749.         if links_possible then begin
  5750.             if s = '' then begin
  5751.                 grab_line('Room name: ',s);
  5752.             end;
  5753.             s := slead(s);
  5754.  
  5755.             createroom(s);
  5756.         end else begin
  5757.             writeln('You may not create any new exits here.  Go to a place where you can create');
  5758.             writeln('an exit before FORMing a new room.');
  5759.         end;
  5760.     end;
  5761. end;
  5762.  
  5763.  
  5764. procedure xpoof; { loc: integer; forward }
  5765. var
  5766.     targslot: integer;
  5767.  
  5768. begin
  5769.     if put_token(loc,targslot,here.people[myslot].hiding) then begin
  5770.         if hiding then begin
  5771.             log_event(myslot,E_HPOOFOUT,0,0,myname,location);
  5772.             log_event(myslot,E_HPOOFIN,0,0,myname,loc);
  5773.         end else begin
  5774.             log_event(myslot,E_POOFOUT,0,0,myname,location);
  5775.             log_event(targslot,E_POOFIN,0,0,myname,loc);
  5776.         end;
  5777.  
  5778.         take_token(myslot,location);
  5779.         myslot := targslot;
  5780.         location := loc;
  5781.         setevent;
  5782.         do_look;
  5783.     end else
  5784.         writeln('There is a crackle of electricity, but the poof fails.');
  5785. end;
  5786.  
  5787.  
  5788. procedure do_poof(s: string);
  5789. var
  5790.     n,loc: integer;
  5791.  
  5792. begin
  5793.     if privd then begin
  5794.         gethere;
  5795.         if lookup_room(loc,s) then begin
  5796.             xpoof(loc);
  5797.         end else if parse_pers(n,s) then begin
  5798.             grab_line('What room? ',s);
  5799.             if lookup_room(loc,s) then begin
  5800.                 log_event(myslot,E_POOFYOU,n,loc);
  5801.                 writeln;
  5802.                 writeln('You extend your arms, muster some energy, and ',here.people[n].name,' is');
  5803.                 writeln('engulfed in a cloud of orange smoke.');
  5804.                 writeln;
  5805.             end else
  5806.                 writeln('There is no room named ',s,'.');
  5807.         end else
  5808.             writeln('There is no room named ',s,'.');
  5809.     end else
  5810.         writeln('Only the Monster Manager may poof.');
  5811. end;
  5812.  
  5813.  
  5814. procedure link_room(origdir,targdir,targroom: integer);
  5815.  
  5816. begin
  5817.     { since exit creation involves the writing of two records,
  5818.       perhaps there should be a global lock around this code,
  5819.       such as a get to some obscure index field or something.
  5820.       I haven't put this in because I don't believe that if this
  5821.       routine fails it will seriously damage the database.
  5822.  
  5823.       Actually, the lock should be on the test (do_link) but that
  5824.       would be hard    }
  5825.  
  5826.     getroom;
  5827.     with here.exits[origdir] do begin
  5828.         toloc := targroom;
  5829.         kind := 1; { type of exit, they can customize later }
  5830.         slot := targdir; { exit it comes out in in target room }
  5831.  
  5832.         init_exit(origdir);
  5833.     end;
  5834.     putroom;
  5835.  
  5836.     log_event(myslot,E_NEWEXIT,0,0,myname,location);
  5837.     if location <> targroom then
  5838.         log_event(0,E_NEWEXIT,0,0,myname,targroom);
  5839.  
  5840.     getroom(targroom);
  5841.     with here.exits[targdir] do begin
  5842.         toloc := location;
  5843.         kind := 1;
  5844.         slot := origdir;
  5845.  
  5846.         init_exit(targdir);
  5847.     end;
  5848.     putroom;
  5849.     writeln('Exit created.  Use CUSTOM ',direct[origdir],' to customize your exit.');
  5850. end;
  5851.  
  5852.  
  5853. {
  5854. User procedure to link a room
  5855. }
  5856. procedure do_link(s: string);
  5857. var
  5858.     ok: boolean;
  5859.     orgexitnam,targnam,trgexitnam: string;
  5860.     targroom,    { number of target room }
  5861.     targdir,    { number of target exit direction }
  5862.     origdir: integer;{ number of exit direction here }
  5863.     firsttime: boolean;
  5864.  
  5865. begin
  5866.  
  5867. {    gethere;    ! done in links_possible }
  5868.  
  5869.    if links_possible then begin
  5870.     log_action(link,0);
  5871.     if checkhide then begin
  5872.     writeln('Hit return alone at any prompt to terminate exit creation.');
  5873.     writeln;
  5874.  
  5875.     if s = '' then
  5876.         firsttime := false
  5877.     else begin
  5878.         orgexitnam := bite(s);
  5879.         firsttime := true;
  5880.     end;
  5881.  
  5882.     repeat
  5883.         if not(firsttime) then
  5884.             grab_line('Direction of exit? ',orgexitnam)
  5885.         else
  5886.             firsttime := false;
  5887.  
  5888.         ok :=lookup_dir(origdir,orgexitnam);
  5889.         if ok then
  5890.             ok := can_make(origdir);
  5891.     until (orgexitnam = '') or ok;
  5892.  
  5893.     if ok then begin
  5894.         if s = '' then
  5895.             firsttime := false
  5896.         else begin
  5897.             targnam := s;
  5898.             firsttime := true;
  5899.         end;
  5900.  
  5901.         repeat
  5902.             if not(firsttime) then
  5903.                 grab_line('Room to link to? ',targnam)
  5904.             else
  5905.                 firsttime := false;
  5906.  
  5907.             ok := lookup_room(targroom,targnam);
  5908.         until (targnam = '') or ok;
  5909.     end;
  5910.  
  5911.     if ok then begin
  5912.         repeat
  5913.             writeln('Exit comes out in target room');
  5914.             grab_line('from what direction? ',trgexitnam);
  5915.             ok := lookup_dir(targdir,trgexitnam);
  5916.             if ok then
  5917.                 ok := can_make(targdir,targroom);
  5918.         until (trgexitnam='') or ok;
  5919.     end;
  5920.  
  5921.     if ok then begin { actually create the exit }
  5922.         link_room(origdir,targdir,targroom);
  5923.     end;
  5924.     end;
  5925.    end else
  5926.     writeln('No links are possible here.');
  5927. end;
  5928.  
  5929.  
  5930. procedure relink_room(origdir,targdir,targroom: integer);
  5931. var
  5932.     tmp: exit;
  5933.     copyslot,
  5934.     copyloc: integer;
  5935.  
  5936. begin
  5937.     gethere;
  5938.     tmp := here.exits[origdir];
  5939.     copyloc := tmp.toloc;
  5940.     copyslot := tmp.slot;
  5941.  
  5942.     getroom(targroom);
  5943.     here.exits[targdir] := tmp;
  5944.     putroom;
  5945.  
  5946.     getroom(copyloc);
  5947.     here.exits[copyslot].toloc := targroom;
  5948.     here.exits[copyslot].slot := targdir;
  5949.     putroom;
  5950.  
  5951.     getroom;
  5952.     here.exits[origdir].toloc := 0;
  5953.     init_exit(origdir);
  5954.     putroom;
  5955. end;
  5956.  
  5957.  
  5958. procedure do_relink(s: string);
  5959. var
  5960.     ok: boolean;
  5961.     orgexitnam,targnam,trgexitnam: string;
  5962.     targroom,    { number of target room }
  5963.     targdir,    { number of target exit direction }
  5964.     origdir: integer;{ number of exit direction here }
  5965.     firsttime: boolean;
  5966.  
  5967. begin
  5968.     log_action(c_relink,0);
  5969.     gethere;
  5970.     if checkhide then begin
  5971.     writeln('Hit return alone at any prompt to terminate exit relinking.');
  5972.     writeln;
  5973.  
  5974.     if s = '' then
  5975.         firsttime := false
  5976.     else begin
  5977.         orgexitnam := bite(s);
  5978.         firsttime := true;
  5979.     end;
  5980.  
  5981.     repeat
  5982.         if not(firsttime) then
  5983.             grab_line('Direction of exit to relink? ',orgexitnam)
  5984.         else
  5985.             firsttime := false;
  5986.  
  5987.         ok :=lookup_dir(origdir,orgexitnam);
  5988.         if ok then
  5989.             ok := can_alter(origdir);
  5990.     until (orgexitnam = '') or ok;
  5991.  
  5992.     if ok then begin
  5993.         if s = '' then
  5994.             firsttime := false
  5995.         else begin
  5996.             targnam := s;
  5997.             firsttime := true;
  5998.         end;
  5999.  
  6000.         repeat
  6001.             if not(firsttime) then
  6002.                 grab_line('Room to relink exit into? ',targnam)
  6003.             else
  6004.                 firsttime := false;
  6005.  
  6006.             ok := lookup_room(targroom,targnam);
  6007.         until (targnam = '') or ok;
  6008.     end;
  6009.  
  6010.     if ok then begin
  6011.         repeat
  6012.             writeln('New exit comes out in target room');
  6013.             grab_line('from what direction? ',trgexitnam);
  6014.             ok := lookup_dir(targdir,trgexitnam);
  6015.             if ok then
  6016.                 ok := can_make(targdir,targroom);
  6017.         until (trgexitnam='') or ok;
  6018.     end;
  6019.  
  6020.     if ok then begin { actually create the exit }
  6021.         relink_room(origdir,targdir,targroom);
  6022.     end;
  6023.     end;
  6024. end;
  6025.  
  6026.  
  6027. { print the room default no-go message if there is one;
  6028.   otherwise supply the generic "you can't go that way" }
  6029.  
  6030. procedure default_fail;
  6031.  
  6032. begin
  6033.     if (here.exitfail <> 0) and (here.exitfail <> DEFAULT_LINE) then
  6034.         print_desc(here.exitfail)
  6035.     else
  6036.         writeln('You can''t go that way.');
  6037. end;
  6038.  
  6039. procedure  exit_fail(dir: integer);
  6040. var
  6041.     tmp: string;
  6042.  
  6043. begin
  6044.     if (dir < 1) or (dir > maxexit) then
  6045.         default_fail
  6046.     else if (here.exits[dir].fail = DEFAULT_LINE) then begin
  6047.         case here.exits[dir].kind of
  6048.             5: writeln('There isn''t an exit there yet.');
  6049.             6: writeln('You don''t have the power to go there.');
  6050.             otherwise default_fail;
  6051.         end;
  6052.     end else if here.exits[dir].fail <> 0 then
  6053.         block_subs(here.exits[dir].fail,myname);
  6054.  
  6055.  
  6056. { now print the exit failure message for everyone else in the room:
  6057.     if they tried to go through a valid exit,
  6058.       and the exit has an other-person failure desc, then
  6059.         substitute that one & use;
  6060.  
  6061.     if there is a room default other-person failure desc, then
  6062.         print that;
  6063.  
  6064.     if they tried to go through a valid exit,
  6065.       and the exit has no required alias, then
  6066.         print default exit fail
  6067.     else
  6068.         print generic "didn't leave room" message
  6069.  
  6070. cases:
  6071. 1) valid/alias exit and specific fail message
  6072. 2) valid/alias exit and blanket fail message
  6073. 3) valid exit (no specific or blanket) "x fails to go [direct]"
  6074. 4) alias exit and blanket fail
  6075. 5) blanket fail
  6076. 6) generic fail
  6077. }
  6078.  
  6079.     if dir <> 0 then
  6080.         log_event(myslot,E_FAILGO,dir,0);
  6081. end;
  6082.  
  6083.  
  6084.  
  6085. procedure do_exit; { (exit_slot: integer)-- declared forward }
  6086. var
  6087.     orig_slot,
  6088.     targ_slot,
  6089.     orig_room,
  6090.     enter_slot,
  6091.     targ_room: integer;
  6092.     doalook: boolean;
  6093.  
  6094. begin
  6095.     if (exit_slot < 1) or (exit_slot > 6) then
  6096.         exit_fail(exit_slot)
  6097.     else if here.exits[exit_slot].toloc > 0 then begin
  6098.         block_subs(here.exits[exit_slot].success,myname);
  6099.  
  6100.         orig_slot := myslot;
  6101.         orig_room := location;
  6102.         targ_room := here.exits[exit_slot].toloc;
  6103.         enter_slot := here.exits[exit_slot].slot;
  6104.         doalook := here.exits[exit_slot].autolook;
  6105.  
  6106.                 { optimization for exit that goes nowhere;
  6107.                   why go nowhere?  For special effects, we
  6108.                   don't want it to take too much time,
  6109.                   the logs are important because they force the
  6110.                   exit descriptions, but actually moving the
  6111.                   player is unnecessary }
  6112.  
  6113.         if orig_room = targ_room then begin
  6114.             log_exit(exit_slot,orig_room,orig_slot);
  6115.             log_entry(enter_slot,targ_room,orig_slot);
  6116.                 { orig_slot in log_entry 'cause we're not
  6117.                   really going anwhere }
  6118.             if doalook then
  6119.                 do_look;
  6120.         end else begin
  6121.             take_token(orig_slot,orig_room);
  6122.             if not put_token(targ_room,targ_slot) then begin
  6123.                     { no room in room! }
  6124. { put them back! Quick! }    if not put_token(orig_room,myslot) then begin
  6125.                     writeln('%Oh no!');
  6126.                     halt;
  6127.                 end;
  6128.             end else begin
  6129.                 log_exit(exit_slot,orig_room,orig_slot);
  6130.                 log_entry(enter_slot,targ_room,targ_slot);
  6131.  
  6132.                 myslot := targ_slot;
  6133.                 location := targ_room;
  6134.                 setevent;
  6135.     
  6136.                 if doalook then
  6137.                     do_look;
  6138.             end;
  6139.         end;
  6140.     end else
  6141.         exit_fail(exit_slot);
  6142. end;
  6143.  
  6144.  
  6145.  
  6146. function cycle_open: boolean;
  6147. var
  6148.     ch: char;
  6149.     s: string;
  6150.  
  6151. begin
  6152.     s := systime;
  6153.     ch := s[5];
  6154.     if ch in ['1','3','5','7','9'] then
  6155.         cycle_open := true
  6156.     else
  6157.         cycle_open := false;
  6158. end;
  6159.  
  6160.  
  6161. function which_dir(var dir:integer;s: string): boolean;
  6162. var
  6163.     aliasdir, exitdir: integer;
  6164.     aliasmatch,exitmatch,
  6165.     aliasexact,exitexact: boolean;
  6166.     exitreq: boolean;
  6167.  
  6168. begin
  6169.     s := lowcase(s);
  6170.     if lookup_alias(aliasdir,s) then
  6171.         aliasmatch := true
  6172.     else
  6173.         aliasmatch := false;
  6174.     if lookup_dir(exitdir,s) then
  6175.         exitmatch := true
  6176.     else
  6177.         exitmatch := false;
  6178.     if aliasmatch then begin
  6179.         if s = here.exits[aliasdir].alias then
  6180.             aliasexact := true
  6181.         else
  6182.             aliasexact := false;
  6183.     end else
  6184.         aliasexact := false;
  6185.     if exitmatch then begin
  6186.         if (s = direct[exitdir]) or (s = substr(direct[exitdir],1,1)) then
  6187.             exitexact := true
  6188.         else
  6189.             exitexact := false;
  6190.     end else
  6191.         exitexact := false;
  6192.     if exitmatch then
  6193.         exitreq := here.exits[exitdir].reqalias
  6194.     else
  6195.         exitreq := false;
  6196.  
  6197.     dir := 0;
  6198.     which_dir := true;
  6199.     if aliasexact and exitexact then
  6200.         dir := aliasdir
  6201.     else if aliasexact then
  6202.         dir := aliasdir
  6203.     else if exitexact and not exitreq then
  6204.         dir := exitdir
  6205.     else if aliasmatch then
  6206.         dir := aliasdir
  6207.     else if exitmatch and not exitreq then
  6208.         dir := exitdir
  6209.     else if exitmatch and exitreq then begin
  6210.         dir := exitdir;
  6211.         which_dir := false;
  6212.     end else begin
  6213.         which_dir := false;
  6214.     end;
  6215. end;
  6216.  
  6217.  
  6218. procedure exit_case(dir: integer);
  6219.  
  6220. begin
  6221.     case here.exits[dir].kind of
  6222.         0: exit_fail(dir);
  6223.         1: do_exit(dir);  { more checking goes here }
  6224.  
  6225.         3: if obj_hold(here.exits[dir].objreq) then
  6226.             exit_fail(dir)
  6227.            else
  6228.             do_exit(dir);
  6229.         4: if rnd100 < 34 then
  6230.             do_exit(dir)
  6231.            else
  6232.             exit_fail(dir);
  6233.  
  6234.         2: begin
  6235.             if obj_hold(here.exits[dir].objreq) then
  6236.                 do_exit(dir)
  6237.             else
  6238.                 exit_fail(dir);
  6239.            end;
  6240.         6: if obj_hold(here.exits[dir].objreq) then
  6241.             do_exit(dir)
  6242.              else
  6243.             exit_fail(dir);
  6244.         7: if cycle_open then
  6245.             do_exit(dir)
  6246.            else
  6247.         exit_fail(dir);
  6248.     end;
  6249. end;
  6250.  
  6251. {
  6252. Player wants to go to s
  6253. Handle everthing, this is the top level procedure
  6254.  
  6255. Check that he can go to s
  6256. Put him through the exit    ( in do_exit )
  6257. Do a look for him        ( in do_exit )
  6258. }
  6259. procedure do_go(s: string;verb:boolean := true);
  6260. var
  6261.     dir: integer;
  6262.  
  6263. begin
  6264.     gethere;
  6265.     if checkhide then begin
  6266.         if length(s) = 0 then
  6267.             writeln('You must give the direction you wish to travel.')
  6268.         else begin
  6269.             if which_dir(dir,s) then begin
  6270.                 if (dir >= 1) and (dir <= maxexit) then begin
  6271.                     if here.exits[dir].toloc = 0 then begin
  6272.                         exit_fail(dir);
  6273.                     end else begin
  6274.                         exit_case(dir);
  6275.                     end;
  6276.                 end else
  6277.                     exit_fail(dir);
  6278.             end else
  6279.                 exit_fail(dir);
  6280.         end;
  6281.     end;
  6282. end;
  6283.  
  6284.  
  6285. procedure nice_say(var s: string);
  6286.  
  6287. begin
  6288.         { capitalize the first letter of their sentence }
  6289.  
  6290.     if s[1] in ['a'..'z'] then
  6291.         s[1] := chr( ord('A') + (ord(s[1]) - ord('a')) );
  6292.  
  6293.             { put a period on the end of their sentence if
  6294.               they don't use any punctuation. }
  6295.  
  6296.     if s[length(s)] in ['a'..'z','A'..'Z'] then
  6297.         s := s + '.';
  6298. end;
  6299.  
  6300.  
  6301. procedure do_say(s:string);
  6302.  
  6303. begin
  6304.     if length(s) > 0 then begin
  6305.  
  6306. {        if length(s) + length(myname) > 79 then begin
  6307.             s := substr(s,1,75-length(myname));
  6308.             writeln('Your message was truncated:');
  6309.             writeln('-- ',s);
  6310.         end;                    }
  6311.  
  6312.         nice_say(s);
  6313.         if hiding then
  6314.             log_event(myslot,E_HIDESAY,0,0,s)
  6315.         else
  6316.             log_event(myslot,E_SAY,0,0,s);
  6317.     end else
  6318.         writeln('To talk to others in the room, type SAY <message>.');
  6319. end;
  6320.  
  6321. procedure do_setname(s: string);
  6322. var
  6323.     notice: string;
  6324.     ok: boolean;
  6325.     dummy: integer;
  6326.     sprime: string;
  6327.  
  6328. begin
  6329.     gethere;
  6330.     if s <> '' then begin
  6331.     if length(s) <= shortlen then begin
  6332.         sprime := lowcase(s);
  6333.         if (sprime = 'monster manager') and (userid <> MM_userid) then begin
  6334.             writeln('Only the Monster Manager can have that personal name.');
  6335.             ok := false;
  6336.         end else if (sprime = 'vice manager') and (userid <> MVM_userid) then begin
  6337.             writeln('Only the Vice Manager can have that name.');
  6338.             ok := false;
  6339.         end else if (sprime = 'faust') and (userid <> FAUST_userid) then begin
  6340.             writeln('You are not Faust!  You may not have that name.');
  6341.             ok := false;
  6342.         end else
  6343.             ok := true;
  6344.  
  6345.         if ok then
  6346.             if exact_pers(dummy,sprime) then begin
  6347.                 if dummy = myslot then
  6348.                     ok := true
  6349.                 else begin
  6350.                     writeln('Someone already has that name.  Your personal name must be unique.');
  6351.                     ok := false;
  6352.                 end;
  6353.             end;
  6354.  
  6355.         if ok then begin
  6356.             myname := s;
  6357.             getroom;
  6358.             notice := here.people[myslot].name;
  6359.             here.people[myslot].name := s;
  6360.             putroom;
  6361.             notice := notice + ' is now known as ' + s;
  6362.  
  6363.             if not(hiding) then
  6364.                 log_event(0,E_SETNAM,0,0,notice);
  6365.                     { slot 0 means notify this player also }
  6366.  
  6367.             getpers;    { note the new personal name in the logfile }
  6368.             pers.idents[mylog] := s; { don't lowcase it }
  6369.             putpers;
  6370.         end;
  6371.     end else
  6372.         writeln('Please limit your personal name to ',shortlen:1,' characters.');
  6373.     end else
  6374.         writeln('You are known to others as ',myname);
  6375. end;
  6376.  
  6377. function sysdate:string;
  6378. var
  6379.     thedate: packed array[1..11] of char;
  6380.  
  6381. begin
  6382.     date(thedate);
  6383.     sysdate := thedate;
  6384. end;
  6385.  
  6386.  
  6387. {
  6388. 1234567890123456789012345678901234567890
  6389. example display for alignment:
  6390.  
  6391.        Monster Status
  6392.     19-MAR-1988 08:59pm
  6393.  
  6394. }
  6395.  
  6396. procedure do_who;
  6397. var
  6398.     i,j: integer;
  6399.     ok: boolean;
  6400.     metaok: boolean;
  6401.     roomown: veryshortstring;
  6402.  
  6403. begin
  6404.     log_event(myslot,E_WHO,0,(rnd100 mod 4));
  6405.  
  6406.     { we need just about everything to print this list:
  6407.         player alloc index, userids, personal names,
  6408.         room names, room owners, and the log record    }
  6409.  
  6410.     getindex(I_ASLEEP);    { Get index of people who are playing now }
  6411.     freeindex;
  6412.     getuser;
  6413.     freeuser;
  6414.     getpers;
  6415.     freepers;
  6416.     getnam;
  6417.     freenam;
  6418.     getown;
  6419.     freeown;
  6420.     getint(N_LOCATION);    { get where they are }
  6421.     freeint;
  6422.     writeln('                   Monster Status');
  6423.     writeln('                ',sysdate,' ',systime);
  6424.     writeln;
  6425.     writeln('Username        Game Name                 Where');
  6426.  
  6427.     if (privd) { or has_kind(O_ALLSEEING) } then
  6428.         metaok := true
  6429.     else
  6430.         metaok := false;
  6431.  
  6432.     for i := 1 to indx.top do begin
  6433.         if not(indx.free[i]) then begin
  6434.             write(user.idents[i]);
  6435.             j := length(user.idents[i]);
  6436.             while j < 16 do begin
  6437.                 write(' ');
  6438.                 j := j + 1;
  6439.             end;
  6440.  
  6441.             write(pers.idents[i]);
  6442.             j := length(pers.idents[i]);
  6443.             while j <= 25 do begin
  6444.                 write(' ');
  6445.                 j := j + 1;
  6446.             end;
  6447.  
  6448.             if not(metaok) then begin
  6449.                 roomown := own.idents[anint.int[i]];
  6450.  
  6451. { if a person is in a public or disowned room, or
  6452.   if they are in the domain of the WHOer, then the player should know
  6453.   where they are  }
  6454.  
  6455.                 if (roomown = '') or (roomown = '*') or
  6456.                     (roomown = userid) then
  6457.                     ok := true
  6458.                 else
  6459.                     ok := false;
  6460.  
  6461.  
  6462. { the player obviously knows where he is }
  6463.                 if i = mylog then
  6464.                     ok := true;
  6465.             end;
  6466.  
  6467.  
  6468.             if ok or metaok then begin
  6469.                 writeln(nam.idents[anint.int[i]]);
  6470.             end else
  6471.                 writeln('n/a');
  6472.         end;
  6473.     end;
  6474. end;
  6475.  
  6476. function own_trans(s: string): string;
  6477.  
  6478. begin
  6479.     if s = '' then
  6480.         own_trans := '<public>'
  6481.     else if s = '*' then
  6482.         own_trans := '<disowned>'
  6483.     else
  6484.         own_trans := s;
  6485. end;
  6486.  
  6487.  
  6488. procedure list_rooms(s: shortstring);
  6489. var
  6490.     first: boolean;
  6491.     i,j,posit: integer;
  6492.  
  6493. begin
  6494.     first := true;
  6495.     posit := 0;
  6496.     for i := 1 to indx.top do begin
  6497.         if (not indx.free[i]) and (own.idents[i] = s) then begin
  6498.             if posit = 3 then begin
  6499.                 posit := 1;
  6500.                 writeln;
  6501.             end else
  6502.                 posit := posit + 1;
  6503.             if first then begin
  6504.                 first := false;
  6505.                 writeln(own_trans(s),':');
  6506.             end;
  6507.             write('    ',nam.idents[i]);
  6508.             for j := length(nam.idents[i]) to 21 do
  6509.                 write(' ');
  6510.         end;
  6511.     end;
  6512.     if posit <> 3 then
  6513.         writeln;
  6514.     if first then
  6515.         writeln('No rooms owned by ',own_trans(s))
  6516.     else
  6517.         writeln;
  6518. end;
  6519.  
  6520.  
  6521. procedure list_all_rooms;
  6522. var
  6523.     i,j: integer;
  6524.     tmp: packed array[1..maxroom] of boolean;
  6525.  
  6526. begin
  6527.     tmp := zero;
  6528.     list_rooms('');        { public rooms first }
  6529.     list_rooms('*');    { disowned rooms next }
  6530.     for i := 1 to indx.top do begin
  6531.         if not(indx.free[i]) and not(tmp[i]) and
  6532.            (own.idents[i] <> '') and (own.idents[i] <> '*') then begin
  6533.                 list_rooms(own.idents[i]);    { player rooms }
  6534.                 for j := 1 to indx.top do
  6535.                     if own.idents[j] = own.idents[i] then
  6536.                         tmp[j] := TRUE;
  6537.         end;
  6538.     end;
  6539. end;
  6540.  
  6541. procedure do_rooms(s: string);
  6542. var
  6543.     cmd: string;
  6544.     id: veryshortstring;
  6545.     listall: boolean;
  6546.  
  6547. begin
  6548.     getnam;
  6549.     freenam;
  6550.     getown;
  6551.     freeown;
  6552.     getindex(I_ROOM);
  6553.     freeindex;
  6554.  
  6555.     listall := false;
  6556.     s := lowcase(s);
  6557.     cmd := bite(s);
  6558.     if cmd = '' then
  6559.         id := userid
  6560.     else if cmd = 'public' then
  6561.         id := ''
  6562.     else if cmd = 'disowned' then
  6563.         id := '*'
  6564.     else if cmd = '<public>' then
  6565.         id := ''
  6566.     else if cmd = '<disowned>' then
  6567.         id := '*'
  6568.     else if cmd = '*' then
  6569.         listall := true
  6570.     else if length(cmd) > veryshortlen then
  6571.         id := substr(cmd,1,veryshortlen)
  6572.     else
  6573.         id := cmd;
  6574.  
  6575.     if listall then begin
  6576.         if privd then
  6577.             list_all_rooms
  6578.         else
  6579.             writeln('You may not obtain a list of all the rooms.');
  6580.     end else begin
  6581.         if privd or (userid = id) or (id = '') or (id = '*') then
  6582.             list_rooms(id)
  6583.         else
  6584.             writeln('You may not list rooms that belong to another player.');
  6585.     end;
  6586. end;
  6587.  
  6588.  
  6589.  
  6590. procedure do_objects;
  6591. var
  6592.     i: integer;
  6593.     total,public,disowned,private: integer;
  6594.  
  6595. begin
  6596.     getobjnam;
  6597.     freeobjnam;
  6598.     getobjown;
  6599.     freeobjown;
  6600.     getindex(I_OBJECT);
  6601.     freeindex;
  6602.  
  6603.     total := 0;
  6604.     public := 0;
  6605.     disowned := 0;
  6606.     private := 0;
  6607.  
  6608.     writeln;
  6609.     for i := 1 to indx.top do begin
  6610.         if not(indx.free[i]) then begin
  6611.             total := total + 1;
  6612.             if objown.idents[i]='' then begin
  6613.                 writeln(i:4,'    ','<public>':12,'    ',objnam.idents[i]);
  6614.                 public := public + 1
  6615.             end else if objown.idents[i]='*' then begin
  6616.                 writeln(i:4,'    ','<disowned>':12,'    ',objnam.idents[i]);
  6617.                 disowned := disowned + 1
  6618.             end else begin
  6619.                 private := private + 1;
  6620.  
  6621.                 if (objown.idents[i] = userid) or
  6622.                  (privd) then begin
  6623. { >>>>>> }    writeln(i:4,'    ',objown.idents[i]:12,'    ',objnam.idents[i]);
  6624.                 end;
  6625.             end;
  6626.         end;
  6627.     end;
  6628.     writeln;
  6629.     writeln('Public:      ',public:4);
  6630.     writeln('Disowned:    ',disowned:4);
  6631.     writeln('Private:     ',private:4);
  6632.     writeln('             ----');
  6633.     writeln('Total:       ',total:4);
  6634. end;
  6635.  
  6636.  
  6637. procedure do_claim(s: string);
  6638. var
  6639.     n: integer;
  6640.     ok: boolean;
  6641.     tmp: string;
  6642.  
  6643. begin
  6644.     if length(s) = 0 then begin    { claim this room }
  6645.         getroom;
  6646.         if (here.owner = '*') or (privd) then begin
  6647.             here.owner := userid;
  6648.             putroom;
  6649.             getown;
  6650.             own.idents[location] := userid;
  6651.             putown;
  6652.             log_event(myslot,E_CLAIM,0,0);
  6653.             writeln('You are now the owner of this room.');
  6654.         end else begin
  6655.             freeroom;
  6656.             if here.owner = '' then
  6657.                 writeln('This is a public room.  You may not claim it.')
  6658.             else
  6659.                 writeln('This room has an owner.');
  6660.         end;
  6661.     end else if lookup_obj(n,s) then begin
  6662.         getobjown;
  6663.         freeobjown;
  6664.         if objown.idents[n] = '' then
  6665.             writeln('That is a public object.  You may DUPLICATE it, but may not CLAIM it.')
  6666.         else if objown.idents[n] <> '*' then
  6667.             writeln('That object has an owner.')
  6668.         else begin
  6669.             getobj(n);
  6670.             freeobj;
  6671.             if obj.numexist = 0 then
  6672.                 ok := true
  6673.             else begin
  6674.                 if obj_hold(n) or obj_here(n) then
  6675.                     ok := true
  6676.                 else
  6677.                     ok := false;
  6678.             end;
  6679.  
  6680.             if ok then begin
  6681.                 getobjown;
  6682.                 objown.idents[n] := userid;
  6683.                 putobjown;
  6684.                 tmp := obj.oname;
  6685.                 log_event(myslot,E_OBJCLAIM,0,0,tmp);
  6686.                 writeln('You are now the owner the ',tmp,'.');
  6687.             end else
  6688.                 writeln('You must have one to claim it.');
  6689.         end;
  6690.     end else
  6691.         writeln('There is nothing here by that name to claim.');
  6692. end;
  6693.  
  6694. procedure do_disown(s: string);
  6695. var
  6696.     n: integer;
  6697.     tmp: string;
  6698.  
  6699. begin
  6700.     if length(s) = 0 then begin    { claim this room }
  6701.         getroom;
  6702.         if (here.owner = userid) or (privd) then begin
  6703.             getroom;
  6704.             here.owner := '*';
  6705.             putroom;
  6706.             getown;
  6707.             own.idents[location] := '*';
  6708.             putown;
  6709.             log_event(myslot,E_DISOWN,0,0);
  6710.             writeln('You have disowned this room.');
  6711.         end else begin
  6712.             freeroom;
  6713.             writeln('You are not the owner of this room.');
  6714.         end;
  6715.     end else begin    { disown an object }
  6716.         if lookup_obj(n,s) then begin
  6717.             getobj(n);
  6718.             freeobj;
  6719.             tmp := obj.oname;
  6720.  
  6721.             getobjown;
  6722.             if objown.idents[n] = userid then begin
  6723.                 objown.idents[n] := '*';
  6724.                 putobjown;
  6725.                 log_event(myslot,E_OBJDISOWN,0,0,tmp);
  6726.                 writeln('You are no longer the owner of the ',tmp,'.');
  6727.             end else begin
  6728.                 freeobjown;
  6729.                 writeln('You are not the owner of any such thing.');
  6730.             end;
  6731.         end else
  6732.             writeln('You are not the owner of any such thing.');
  6733.     end;
  6734. end;
  6735.  
  6736.  
  6737. procedure do_public(s: string);
  6738. var
  6739.     ok: boolean;
  6740.     tmp: string;
  6741.     n: integer;
  6742.  
  6743. begin
  6744.     if privd then begin
  6745.         if length(s) = 0 then begin
  6746.             getroom;
  6747.             here.owner := '';
  6748.             putroom;
  6749.             getown;
  6750.             own.idents[location] := '';
  6751.             putown;
  6752.         end else if lookup_obj(n,s) then begin
  6753.             getobjown;
  6754.             freeobjown;
  6755.             if objown.idents[n] = '' then
  6756.                 writeln('That is already public.')
  6757.             else begin
  6758.                 getobj(n);
  6759.                 freeobj;
  6760.                 if obj.numexist = 0 then
  6761.                     ok := true
  6762.                 else begin
  6763.                     if obj_hold(n) or obj_here(n) then
  6764.                         ok := true
  6765.                     else
  6766.                         ok := false;
  6767.                 end;
  6768.  
  6769.                 if ok then begin
  6770.                     getobjown;
  6771.                     objown.idents[n] := '';
  6772.                     putobjown;
  6773.  
  6774.                     tmp := obj.oname;
  6775.                     log_event(myslot,E_OBJPUBLIC,0,0,tmp);
  6776.                     writeln('The ',tmp,' is now public.');
  6777.                 end else
  6778.                     writeln('You must have one to claim it.');
  6779.             end;
  6780.         end else
  6781.             writeln('There is nothing here by that name to claim.');
  6782.     end else
  6783.         writeln('Only the Monster Manager may make things public.');
  6784. end;
  6785.  
  6786.  
  6787.  
  6788. { sum up the number of real exits in this room }
  6789.  
  6790. function find_numexits: integer;
  6791. var
  6792.     i: integer;
  6793.     sum: integer;
  6794.  
  6795. begin
  6796.     sum := 0;
  6797.     for i := 1 to maxexit do
  6798.         if here.exits[i].toloc <> 0 then
  6799.             sum := sum + 1;
  6800.     find_numexits := sum;
  6801. end;
  6802.  
  6803.  
  6804.  
  6805. { clear all people who have played monster and quit in this location
  6806.   out of the room so that when they start up again they won't be here,
  6807.   because we are destroying this room }
  6808.  
  6809. procedure clear_people(loc: integer);
  6810. var
  6811.     i: integer;
  6812.  
  6813. begin
  6814.     getint(N_LOCATION);
  6815.     for i := 1 to maxplayers do
  6816.         if anint.int[i] = loc then
  6817.             anint.int[i] := 1;
  6818.     putint;
  6819. end;
  6820.  
  6821.  
  6822. procedure do_zap(s: string);
  6823. var
  6824.     loc: integer;
  6825.  
  6826. begin
  6827.     gethere;
  6828.     if checkhide then begin
  6829.     if lookup_room(loc,s) then begin
  6830.         gethere(loc);
  6831.         if (here.owner = userid) or (privd) then begin
  6832.             clear_people(loc);
  6833.             if find_numpeople = 0 then begin
  6834.                 if find_numexits = 0 then begin
  6835.                     if find_numobjs = 0 then begin
  6836.                         del_room(loc);
  6837.                         writeln('Room deleted.');
  6838.                     end else
  6839.                         writeln('You must remove all of the objects from that room first.');
  6840.                 end else
  6841.                     writeln('You must delete all of the exits from that room first.');
  6842.             end else
  6843.                 writeln('Sorry, you cannot destroy a room if people are still in it.');
  6844.         end else
  6845.             writeln('You are not the owner of that room.');
  6846.     end else
  6847.         writeln('There is no room named ',s,'.');
  6848.     end;
  6849. end;
  6850.  
  6851.  
  6852. function room_nameinuse(num: integer; newname: string): boolean;
  6853. var
  6854.     dummy: integer;
  6855.  
  6856. begin
  6857.     if exact_obj(dummy,newname) then begin
  6858.         if dummy = num then
  6859.             room_nameinuse := false
  6860.         else
  6861.             room_nameinuse := true;
  6862.     end else
  6863.         room_nameinuse := false;
  6864. end;
  6865.  
  6866.  
  6867.  
  6868. procedure do_rename;
  6869. var
  6870.     dummy: integer;
  6871.     newname: string;
  6872.     s: string;
  6873.  
  6874. begin
  6875.     gethere;
  6876.     writeln('This room is named ',here.nicename);
  6877.     writeln;
  6878.     grab_line('New name: ',newname);
  6879.     if (newname = '') or (newname = '**') then
  6880.         writeln('No changes.')
  6881.     else if length(newname) > shortlen then
  6882.         writeln('Please limit your room name to ',shortlen:1,' characters.')
  6883.     else if room_nameinuse(location,newname) then
  6884.         writeln(newname,' is not a unique room name.')
  6885.     else begin
  6886.         getroom;
  6887.         here.nicename := newname;
  6888.         putroom;
  6889.  
  6890.         getnam;
  6891.         nam.idents[location] := lowcase(newname);
  6892.         putnam;
  6893.         writeln('Room name updated.');
  6894.     end;
  6895. end;
  6896.  
  6897.  
  6898. function obj_nameinuse(objnum: integer; newname: string): boolean;
  6899. var
  6900.     dummy: integer;
  6901.  
  6902. begin
  6903.     if exact_obj(dummy,newname) then begin
  6904.         if dummy = objnum then
  6905.             obj_nameinuse := false
  6906.         else
  6907.             obj_nameinuse := true;
  6908.     end else
  6909.         obj_nameinuse := false;
  6910. end;
  6911.  
  6912.  
  6913. procedure do_objrename(objnum: integer);
  6914. var
  6915.     newname: string;
  6916.     s: string;
  6917.  
  6918. begin
  6919.     getobj(objnum);
  6920.     freeobj;
  6921.  
  6922.     writeln('This object is named ',obj.oname);
  6923.     writeln;
  6924.     grab_line('New name: ',newname);
  6925.     if (newname = '') or (newname = '**') then
  6926.         writeln('No changes.')
  6927.     else if length(newname) > shortlen then
  6928.         writeln('Please limit your object name to ',shortlen:1,' characters.')
  6929.     else if obj_nameinuse(objnum,newname) then
  6930.         writeln(newname,' is not a unique object name.')
  6931.     else begin
  6932.         getobj(objnum);
  6933.         obj.oname := newname;
  6934.         putobj;
  6935.  
  6936.         getobjnam;
  6937.         objnam.idents[objnum] := lowcase(newname);
  6938.         putobjnam;
  6939.         writeln('Object name updated.');
  6940.     end;
  6941. end;
  6942.  
  6943.  
  6944.  
  6945. procedure view_room;
  6946. var
  6947.     s: string;
  6948.     i: integer;
  6949.  
  6950. begin
  6951.     writeln;
  6952.     getnam;
  6953.     freenam;
  6954.     getobjnam;
  6955.     freeobjnam;
  6956.  
  6957.     with here do begin
  6958.         writeln('Room:        ',nicename);
  6959.         case nameprint of
  6960.             0: writeln('Room name not printed');
  6961.             1: writeln('"You''re in" precedes room name');
  6962.             2: writeln('"You''re at" precedes room name');
  6963.             otherwise writeln('Room name printing is damaged.');
  6964.         end;
  6965.  
  6966.         write('Room owner:    ');
  6967.         if owner = '' then
  6968.             writeln('<public>')
  6969.         else if owner = '*' then
  6970.             writeln('<disowned>')
  6971.         else
  6972.             writeln(owner);
  6973.  
  6974.         if primary = 0 then
  6975.             writeln('There is no primary description')
  6976.         else
  6977.             writeln('There is a primary description');
  6978.  
  6979.         if secondary = 0 then
  6980.             writeln('There is no secondary description')
  6981.         else
  6982.             writeln('There is a secondary description');
  6983.  
  6984.         case which of
  6985.             0: writeln('Only the primary description will print');
  6986.             1: writeln('Only the secondary description will print');
  6987.             2: writeln('Both the primary and secondary descriptions will print');
  6988.             3: begin
  6989.                 writeln('The primary description will print, followed by the seconary description');
  6990.                 writeln('if the player is holding the magic object');
  6991.                end;
  6992.             4: begin
  6993.                 writeln('If the player is holding the magic object, the secondary description will print');
  6994.                 writeln('Otherwise, the primary description will print');
  6995.                end;
  6996.             otherwise writeln('The way the room description prints is damaged');
  6997.         end;
  6998.  
  6999.         writeln;
  7000.         if magicobj = 0 then
  7001.             writeln('There is no magic object for this room')
  7002.         else
  7003.             writeln('The magic object for this room is the ',objnam.idents[magicobj],'.');
  7004.  
  7005.         if objdrop = 0 then
  7006.             writeln('Dropped objects remain here')
  7007.         else begin
  7008.             writeln('Dropped objects go to ',nam.idents[objdrop],'.');
  7009.             if objdesc = 0 then
  7010.                 writeln('Dropped.')
  7011.             else
  7012.                 print_line(objdesc);
  7013.             if objdest = 0 then
  7014.                 writeln('Nothing is printed when object "bounces in" to target room')
  7015.             else
  7016.                 print_line(objdest);
  7017.         end;
  7018.         writeln;
  7019.         if trapto = 0 then
  7020.             writeln('There is no trapdoor set')
  7021.         else
  7022.             writeln('The trapdoor sends players ',direct[trapto],
  7023.                 ' with a chance factor of ',trapchance:1,'%');
  7024.  
  7025.         for i := 1 to maxdetail do begin
  7026.             if length(detail[i]) > 0 then begin
  7027.                 write('Detail "',detail[i],'" ');
  7028.                 if detaildesc[i] > 0 then
  7029.                     writeln('has a description')
  7030.                 else
  7031.                     writeln('has no description');
  7032.             end;
  7033.         end;
  7034.         writeln;
  7035.     end;
  7036. end;
  7037.  
  7038.  
  7039. procedure room_help;
  7040.  
  7041. begin
  7042.     writeln;
  7043.     writeln('D    Alter the way the room description prints');
  7044.     writeln('N    Change how the room Name prints');
  7045.     writeln('P    Edit the Primary room description [the default one] (same as desc)');
  7046.     writeln('S    Edit the Secondary room description');
  7047.     writeln('X    Define a mystery message');
  7048.     writeln;
  7049.     writeln('G    Set the location that a dropped object really Goes to');
  7050.     writeln('O    Edit the object drop description (for drop effects)');
  7051.     writeln('B    Edit the target room (G) "bounced in" description');
  7052.     writeln;
  7053.     writeln('T    Set the direction that the Trapdoor goes to');
  7054.     writeln('C    Set the Chance of the trapdoor functioning');
  7055.     writeln;
  7056.     writeln('M    Define the magic object for this room');
  7057.     writeln('R    Rename the room');
  7058.     writeln;
  7059.     writeln('V    View settings on this room');
  7060.     writeln('E    Exit (same as quit)');
  7061.     writeln('Q    Quit (same as exit)');
  7062.     writeln('?    This list');
  7063.     writeln;
  7064. end;
  7065.  
  7066.  
  7067.  
  7068. procedure custom_room;
  7069. var
  7070.     done: boolean;
  7071.     prompt: string;
  7072.     n: integer;
  7073.     s: string;
  7074.     newdsc: integer;
  7075.     bool: boolean;
  7076.  
  7077. begin
  7078.     log_action(e_custroom,0);
  7079.     writeln;
  7080.     writeln('Customizing this room');
  7081.     writeln('If you would rather be customizing an exit, type CUSTOM <direction of exit>');
  7082.     writeln('If you would rather be customizing an object, type CUSTOM <object name>');
  7083.     writeln;
  7084.     done := false;
  7085.     prompt := 'Custom> ';
  7086.  
  7087.     repeat
  7088.         repeat
  7089.             grab_line(prompt,s);
  7090.             s := slead(s);
  7091.         until length(s) > 0;
  7092.         s := lowcase(s);
  7093.         case s[1] of
  7094.  
  7095.             'e','q': done := true;
  7096.             '?','h': room_help;
  7097.             'r': do_rename;
  7098.             'v': view_room;
  7099. {dir trapdoor goes}    't': begin
  7100.                 grab_line('What direction does the trapdoor exit through? ',s);
  7101.                 if length(s) > 0 then begin
  7102.                     if lookup_dir(n,s) then begin
  7103.                         getroom;
  7104.                         here.trapto := n;
  7105.                         putroom;
  7106.                         writeln('Room updated.');
  7107.                     end else
  7108.                         writeln('No such direction.');
  7109.                 end else
  7110.                     writeln('No changes.');
  7111.                  end;
  7112. {chance}        'c': begin
  7113.                 writeln('Enter the chance that in any given minute the player will fall through');
  7114.                 writeln('the trapdoor (0-100) :');
  7115.                 writeln;
  7116.                 grab_line('? ',s);
  7117.                 if isnum(s) then begin
  7118.                     n := number(s);
  7119.                     if n in [0..100] then begin
  7120.                         getroom;
  7121.                         here.trapchance := n;
  7122.                         putroom;
  7123.                     end else
  7124.                         writeln('Out of range.');
  7125.                 end else
  7126.                     writeln('No changes.');
  7127.                  end;
  7128.             's': begin
  7129.                 newdsc := here.secondary;
  7130.                 writeln('[ Editing the secondary room description ]');
  7131.                 if edit_desc(newdsc) then begin
  7132.                     getroom;
  7133.                     here.secondary := newdsc;
  7134.                     putroom;
  7135.                 end;
  7136.                  end;
  7137.             'p': begin
  7138. { same as desc }        newdsc := here.primary;
  7139.                 writeln('[ Editing the primary room description ]');
  7140.                 if edit_desc(newdsc) then begin
  7141.                     getroom;
  7142.                     here.primary := newdsc;
  7143.                     putroom;
  7144.                 end;
  7145.                  end;
  7146.             'o': begin
  7147.                 writeln('Enter the line that will be printed when someone drops an object here:');
  7148.                 writeln('If dropped objects do not stay here, you may use a # for the object name.');
  7149.                 writeln('Right now it says:');
  7150.                 if here.objdesc = 0 then
  7151.                     writeln('Dropped. [default]')
  7152.                 else
  7153.                     print_line(here.objdesc);
  7154.  
  7155.                 n := here.objdesc;
  7156.                 make_line(n);
  7157.                 getroom;
  7158.                 here.objdesc := n;
  7159.                 putroom;
  7160.                  end;
  7161.             'x': begin
  7162.                 writeln('Enter a line that will be randomly shown.');
  7163.                 writeln('Right now it says:');
  7164.                 if here.objdesc = 0 then
  7165.                     writeln('[none defined]')
  7166.                 else
  7167.                     print_line(here.rndmsg);
  7168.  
  7169.                 n := here.rndmsg;
  7170.                 make_line(n);
  7171.                 getroom;
  7172.                 here.rndmsg := n;
  7173.                 putroom;
  7174.                  end;
  7175. {bounced in desc}    'b': begin
  7176.                 writeln('Enter the line that will be displayed in the room where an object really');
  7177.                 writeln('goes when an object dropped here "bounces" there:');
  7178.                 writeln('Place a # where the object name should go.');
  7179.                 writeln;
  7180.                 writeln('Right now it says:');
  7181.                 if here.objdest = 0 then
  7182.                     writeln('Something has bounced into the room.')
  7183.                 else
  7184.                     print_line(here.objdest);
  7185.  
  7186.                 n := here.objdest;
  7187.                 make_line(n);
  7188.                 getroom;
  7189.                 here.objdest := n;
  7190.                 putroom;
  7191.                  end;
  7192.             'm': begin
  7193.                 getobjnam;
  7194.                 freeobjnam;
  7195.                 if here.magicobj = 0 then
  7196.                     writeln('There is currently no magic object for this room.')
  7197.                 else
  7198.                     writeln(objnam.idents[here.magicobj],
  7199.                         ' is currently the magic object for this room.');
  7200.                 writeln;
  7201.                 grab_line('New magic object? ',s);
  7202.                 if s = '' then
  7203.                     writeln('No changes.')
  7204.                 else if lookup_obj(n,s) then begin
  7205.                     getroom;
  7206.                     here.magicobj := n;
  7207.                     putroom;
  7208.                     writeln('Room updated.');
  7209.                 end else
  7210.                     writeln('No such object found.');
  7211.                  end;
  7212.             'g': begin
  7213.                 getnam;
  7214.                 freenam;
  7215.                 if here.objdrop = 0 then
  7216.                     writeln('Objects dropped fall here.')
  7217.                 else
  7218.                     writeln('Objects dropped fall in ',nam.idents[here.objdrop],'.');
  7219.                 writeln;
  7220.                 writeln('Enter * for [this room]:');
  7221.                 grab_line('Room dropped objects go to? ',s);
  7222.                 if s = '' then
  7223.                     writeln('No changes.')
  7224.                 else if s = '*' then begin
  7225.                     getroom;
  7226.                     here.objdrop := 0;
  7227.                     putroom;
  7228.                     writeln('Room updated.');
  7229.                 end else if lookup_room(n,s) then begin
  7230.                     getroom;
  7231.                     here.objdrop := n;
  7232.                     putroom;
  7233.                     writeln('Room updated.');
  7234.                 end else
  7235.                     writeln('No such room found.');
  7236.                  end;
  7237.             'd': begin
  7238.                 writeln('Print room descriptions how?');
  7239.                 writeln;
  7240.                 writeln('0)  Print primary (main) description only [default]');
  7241.                 writeln('1)  Print only secondary description.');
  7242.                 writeln('2)  Print both primary and secondary descriptions togther.');
  7243.                 writeln('3)  Print primary description first; then print secondary description only if');
  7244.                 writeln('    the player is holding the magic object for this room.');
  7245.                 writeln('4)  Print secondary if holding the magic obj; print primary otherwise');
  7246.                 writeln;
  7247.                 grab_line('? ',s);
  7248.                 if isnum(s) then begin
  7249.                     n := number(s);
  7250.                     if n in [0..4] then begin
  7251.                         getroom;
  7252.                         here.which := n;
  7253.                         putroom;
  7254.                         writeln('Room updated.');
  7255.                     end else
  7256.                         writeln('Out of range.');
  7257.                 end else
  7258.                     writeln('No changes.');
  7259.  
  7260.                  end;
  7261.             'n': begin
  7262.                 writeln('How would you like the room name to print?');
  7263.                 writeln;
  7264.                 writeln('0) No room name is shown');
  7265.                 writeln('1) "You''re in ..."');
  7266.                 writeln('2) "You''re at ..."');
  7267.                 writeln;
  7268.                 grab_line('? ',s);
  7269.                 if isnum(s) then begin
  7270.                     n := number(s);
  7271.                     if n in [0..2] then begin
  7272.                         getroom;
  7273.                         here.nameprint := n;
  7274.                         putroom;
  7275.                     end else
  7276.                         writeln('Out of range.');
  7277.                 end else
  7278.                     writeln('No changes.');
  7279.                  end;
  7280.             otherwise writeln('Bad command, type ? for a list');
  7281.         end;
  7282.     until done;
  7283.     log_event(myslot,E_ROOMDONE,0,0);
  7284. end;
  7285.  
  7286. procedure analyze_exit(dir: integer);
  7287. var
  7288.     s: string;
  7289.  
  7290. begin
  7291.     writeln;
  7292.     getnam;
  7293.     freenam;
  7294.     getobjnam;
  7295.     freeobjnam;
  7296.     with here.exits[dir] do begin
  7297.         s := alias;
  7298.         if s = '' then
  7299.             s := '(no alias)'
  7300.         else
  7301.             s := '(alias ' + s + ')';
  7302.         if here.exits[dir].reqalias then
  7303.             s := s + ' (required)'
  7304.         else
  7305.             s := s + ' (not required)';
  7306.  
  7307.         if toloc <> 0 then
  7308.             writeln('The ',direct[dir],' exit ',s,' goes to ',nam.idents[toloc])
  7309.         else
  7310.             writeln('The ',direct[dir],' exit goes nowhere.');
  7311.         if hidden <> 0 then
  7312.             writeln('Concealed.');
  7313.         write('Exit type: ');
  7314.         case kind of
  7315.             0: writeln('no exit.');
  7316.             1: writeln('Open passage.');
  7317.             2: writeln('Door, object required to pass.');
  7318.             3: writeln('No passage if holding object.');
  7319.             4: writeln('Randomly fails');
  7320.             5: writeln('Potential exit.');
  7321.             6: writeln('Only exists while holding the required object.');
  7322.             7: writeln('Timed exit');
  7323.         end;
  7324.         if objreq = 0 then
  7325.             writeln('No required object.')
  7326.         else
  7327.             writeln('Required object is: ',objnam.idents[objreq]);
  7328.  
  7329.  
  7330.         writeln;
  7331.         if exitdesc = DEFAULT_LINE then
  7332.             exit_default(dir,kind)
  7333.         else
  7334.             print_line(exitdesc);
  7335.  
  7336.         if success = 0 then
  7337.             writeln('(no success message)')
  7338.         else
  7339.             print_desc(success);
  7340.  
  7341.         if fail = DEFAULT_LINE then begin
  7342.             if kind = 5 then
  7343.                 writeln('There isn'' an exit there yet.')
  7344.             else
  7345.                 writeln('You can''t go that way.');
  7346.         end else
  7347.             print_desc(fail);
  7348.  
  7349.         if comeout = DEFAULT_LINE then
  7350.             writeln('# has come into the room from: ',direct[dir])
  7351.         else
  7352.             print_desc(comeout);
  7353.         if goin = DEFAULT_LINE then
  7354.             writeln('# has gone ',direct[dir])
  7355.         else
  7356.             print_desc(goin);
  7357.  
  7358.         writeln;
  7359.         if autolook then
  7360.             writeln('LOOK automatically done after exit used')
  7361.         else
  7362.             writeln('LOOK supressed on exit use');
  7363.         if reqverb then
  7364.             writeln('The alias is required to be a verb for exit use')
  7365.         else
  7366.             writeln('The exit can be used with GO or as a verb');
  7367.     end;
  7368.     writeln;
  7369. end;
  7370.  
  7371. procedure custom_help;
  7372.  
  7373. begin
  7374.     writeln;
  7375.     writeln('A    Set an Alias for the exit');
  7376.     writeln('C    Conceal an exit');
  7377.     writeln('D    Edit the exit''s main Description');
  7378.     writeln('E    EXIT custom (saves changes)');
  7379.     writeln('F    Edit the exit''s failure line');
  7380.     writeln('I    Edit the line that others see when a player goes Into an exit');
  7381.     writeln('K    Set the object that is the Key to this exit');
  7382.     writeln('L    Automatically look [default] / don''t look on exit');
  7383.     writeln('O    Edit the line that people see when a player comes Out of an exit');
  7384.     writeln('Q    QUIT Custom (saves changes)');
  7385.     writeln('R    Require/don''t require alias for exit; ignore direction');
  7386.     writeln('S    Edit the success line');
  7387.     writeln('T    Alter Type of exit (passage, door, etc)');
  7388.     writeln('V    View exit information');
  7389.     writeln('X    Require/don''t require exit name to be a verb');
  7390.     writeln('?    This list');
  7391.     writeln;
  7392. end;
  7393.  
  7394.  
  7395. procedure get_key(dir: integer);
  7396. var
  7397.     s: string;
  7398.     n: integer;
  7399.  
  7400. begin
  7401.     getobjnam;
  7402.     freeobjnam;
  7403.     if here.exits[dir].objreq = 0 then
  7404.         writeln('Currently there is no key set for this exit.')
  7405.     else
  7406.         writeln(objnam.idents[here.exits[dir].objreq],' is the current key for this exit.');
  7407.     writeln('Enter * for [no key]');
  7408.     writeln;
  7409.  
  7410.     grab_line('What object is the door key? ',s);
  7411.     if length(s) > 0 then begin
  7412.         if s = '*' then begin
  7413.             getroom;
  7414.             here.exits[dir].objreq := 0;
  7415.             putroom;
  7416.             writeln('Exit updated.');
  7417.         end else if lookup_obj(n,s) then begin
  7418.             getroom;
  7419.             here.exits[dir].objreq := n;
  7420.             putroom;
  7421.             writeln('Exit updated.');
  7422.         end else
  7423.             writeln('There is no object by that name.');
  7424.     end else
  7425.         writeln('No changes.');
  7426. end;
  7427.  
  7428.  
  7429. procedure do_custom(dirnam: string);
  7430. var
  7431.     prompt: string;
  7432.     done : boolean;
  7433.     s: string;
  7434.     dir: integer;
  7435.     n: integer;
  7436.  
  7437. begin
  7438.     gethere;
  7439.     if checkhide then begin
  7440.     if length(dirnam) = 0 then begin
  7441.         if is_owner(location,TRUE) then
  7442.             custom_room
  7443.         else begin
  7444.             writeln('You are not the owner of this room; you cannot customize it.');
  7445.             writeln('However, you may be able to customize some of the exits.  To customize an');
  7446.             writeln('exit, type CUSTOM <direction of exit>');
  7447.         end;
  7448.     end else if lookup_dir(dir,dirnam) then begin
  7449.        if can_alter(dir) then begin
  7450.         log_action(c_custom,0);
  7451.  
  7452.         writeln('Customizing ',direct[dir],' exit');
  7453.         writeln('If you would rather be customizing this room, type CUSTOM with no arguments');
  7454.         writeln('If you would rather be customizing an object, type CUSTOM <object name>');
  7455.         writeln;
  7456.         writeln('Type ** for any line to leave it unchanged.');
  7457.         writeln('Type return for any line to select the default.');
  7458.         writeln;
  7459.         writev(prompt,'Custom ',direct[dir],'> ');
  7460.         done := false;
  7461.         repeat
  7462.             repeat
  7463.                 grab_line(prompt,s);
  7464.                 s := slead(s);
  7465.             until length(s) > 0;
  7466.             s := lowcase(s);
  7467.             case s[1] of
  7468.                 '?','h': custom_help;
  7469.                 'q','e': done := true;
  7470.                 'k': get_key(dir);
  7471.                 'c': begin
  7472.                     writeln('Type the description that a player will see when the exit is found.');
  7473.                     writeln('Make no text for description to unconceal the exit.');
  7474.                     writeln;
  7475.                     writeln('[ Editing the "hidden exit found" description ]');
  7476.                     n := here.exits[dir].hidden;
  7477.                     if edit_desc(n) then begin
  7478.                         getroom;
  7479.                         here.exits[dir].hidden := n;
  7480.                         putroom;
  7481.                     end;
  7482.                      end;
  7483. {req alias}            'r': begin
  7484.                     getroom;
  7485.                     here.exits[dir].reqalias :=
  7486.                         not(here.exits[dir].reqalias);
  7487.                     putroom;
  7488.  
  7489.                     if here.exits[dir].reqalias then
  7490.                         writeln('The alias for this exit will be required to reference it.')
  7491.                     else
  7492.                         writeln('The alias will not be required to reference this exit.');
  7493.                      end;
  7494. {req verb}            'x': begin
  7495.                     getroom;
  7496.                     here.exits[dir].reqverb :=
  7497.                         not(here.exits[dir].reqverb);
  7498.                     putroom;
  7499.  
  7500.                     if here.exits[dir].reqverb then
  7501.                         writeln('The exit name will be required to be used as a verb to use the exit')
  7502.                     else
  7503.                         writeln('The exit name may be used with GO or as a verb to use the exit');
  7504.                      end;
  7505. {autolook}            'l': begin
  7506.                     getroom;
  7507.                     here.exits[dir].autolook :=
  7508.                         not(here.exits[dir].autolook);
  7509.                     putroom;
  7510.  
  7511.                     if here.exits[dir].autolook then
  7512.                         writeln('A LOOK will be done after the player travels through this exit.')
  7513.                     else
  7514.                         writeln('The automatic LOOK will not be done when a player uses this exit.');
  7515.                      end;
  7516.                 'a': begin
  7517.                     grab_line('Alternate name for the exit? ',s);
  7518.                     if length(s) > veryshortlen then
  7519.                         writeln('Your alias must be less than ',veryshortlen:1,' characters.')
  7520.                     else begin
  7521.                         getroom;
  7522.                         here.exits[dir].alias := lowcase(s);
  7523.                         putroom;
  7524.                     end;
  7525.                      end;
  7526.                 'v': analyze_exit(dir);
  7527.                 't': begin
  7528.                     writeln;
  7529.                     writeln('Select the type of your exit:');
  7530.                     writeln;
  7531.                     writeln('0) No exit');
  7532.                     writeln('1) Open passage');
  7533.                     writeln('2) Door (object required to pass)');
  7534.                     writeln('3) No passage if holding key');
  7535.                     if privd then
  7536.                         writeln('4) exit randomly fails');
  7537.                     writeln('6) Exit exists only when holding object');
  7538.                     if privd then
  7539.                         writeln('7) exit opens/closes invisibly every minute');
  7540.                     writeln;
  7541.                     grab_line('Which type? ',s);
  7542.                     if isnum(s) then begin
  7543.                         n := number(s);
  7544.                         if n in [0..4,6..7] then begin
  7545.                             getroom;
  7546.                             here.exits[dir].kind := n;
  7547.                             putroom;
  7548.                             writeln('Exit type updated.');
  7549.                             writeln;
  7550.                             if n in [2,6] then
  7551.                                 get_key(dir);
  7552.                         end else
  7553.                             writeln('Bad exit type.');
  7554.                     end else
  7555.                         writeln('Exit type not changed.');
  7556.                      end;
  7557.                 'f': begin
  7558.                     writeln('The failure description will print if the player attempts to go through the');
  7559.                     writeln('the exit but cannot for any reason.');
  7560.                     writeln;
  7561.                     writeln('[ Editing the exit failure description ]');
  7562.  
  7563.                     n := here.exits[dir].fail;
  7564.                     if edit_desc(n) then begin
  7565.                         getroom;
  7566.                         here.exits[dir].fail := n;
  7567.                         putroom;
  7568.                     end;
  7569.                      end;
  7570.                 'i': begin
  7571.                     writeln('Edit the description that other players see when someone goes into');
  7572.                     writeln('the exit.  Place a # where the player''s name should appear.');
  7573.                     writeln;
  7574.                     writeln('[ Editing the exit "go in" description ]');
  7575.                     n := here.exits[dir].goin;
  7576.                     if edit_desc(n) then begin
  7577.                         getroom;
  7578.                         here.exits[dir].goin := n;
  7579.                         putroom;
  7580.                     end;
  7581.                      end;
  7582.                 'o': begin
  7583.                     writeln('Edit the description that other players see when someone comes out of');
  7584.                     writeln('the exit.  Place a # where the player''s name should appear.');
  7585.                     writeln;
  7586.                     writeln('[ Editing the exit "come out of" description ]');
  7587.                     n := here.exits[dir].comeout;
  7588.                     if edit_desc(n) then begin
  7589.                         getroom;
  7590.                         here.exits[dir].comeout := n;
  7591.                         putroom;
  7592.                     end;
  7593.                      end;
  7594. { main exit desc }        'd': begin
  7595.                     writeln('Enter a one line description of the exit.');
  7596.                     writeln;
  7597.                     n := here.exits[dir].exitdesc;
  7598.                     make_line(n);
  7599.                     getroom;
  7600.                     here.exits[dir].exitdesc := n;
  7601.                     putroom;
  7602.                      end;
  7603.                 's': begin
  7604.                     writeln('The success description will print when the player goes through the exit.');
  7605.                     writeln;
  7606.                     writeln('[ Editing the exit success description ]');
  7607.  
  7608.                     n := here.exits[dir].success;
  7609.                     if edit_desc(n) then begin
  7610.                         getroom;
  7611.                         here.exits[dir].success := n;
  7612.                         putroom;
  7613.                     end;
  7614.                      end;
  7615.                 otherwise writeln('-- Bad command, type ? for a list');
  7616.             end;
  7617.         until done;
  7618.  
  7619.  
  7620.         log_event(myslot,E_CUSTDONE,0,0);
  7621.        end else
  7622.         writeln('You are not allowed to alter that exit.');
  7623.     end else if lookup_obj(n,dirnam) then
  7624. { if lookup_obj returns TRUE then dirnam is name of object to custom }
  7625.                 do_program(dirnam)    { customize the object }
  7626.             else begin
  7627.         writeln('To customize this room, type CUSTOM');
  7628.         writeln('To customize an exits, type CUSTOM <direction>');
  7629.         writeln('To customize an object, type CUSTOM <object name>');
  7630.     end;
  7631. {    clear_command;    }
  7632.     end;
  7633. end;
  7634.  
  7635.  
  7636.  
  7637. procedure reveal_people(var three: boolean);
  7638. var
  7639.     retry,i: integer;
  7640.  
  7641. begin
  7642.     if debug then
  7643.         writeln('%revealing people');
  7644.     three := false;
  7645.     retry := 1;
  7646.  
  7647.     repeat
  7648.         retry := retry + 1;
  7649.         i := (rnd100 mod maxpeople) + 1;
  7650.         if (here.people[i].hiding > 0) and
  7651.                 (i <> myslot) then begin
  7652.             three := true;
  7653.             writeln('You''ve found ',here.people[i].name,' hiding in the shadows!');
  7654.             log_event(myslot,E_FOUNDYOU,i,0);
  7655.         end;
  7656.     until (retry > 7) or three;
  7657. end;
  7658.  
  7659.  
  7660.  
  7661. procedure reveal_objects(var two: boolean);
  7662. var
  7663.     tmp: string;
  7664.     i: integer;
  7665.  
  7666. begin
  7667.     if debug then
  7668.         writeln('%revealing objects');
  7669.     two := false;
  7670.     for i := 1 to maxobjs do begin
  7671.         if here.objs[i] <> 0 then    { if there is an object here }
  7672.             if (here.objhide[i] <> 0) then begin
  7673.                 two := true;
  7674.  
  7675.                 if here.objhide[i] = DEFAULT_LINE then
  7676.                     writeln('You''ve found ',obj_part(here.objs[i]),'.')
  7677.                 else begin
  7678.                     print_desc(here.objhide[i]);
  7679.                     delete_block(here.objhide[i]);
  7680.                 end;
  7681.             end;
  7682.     end;
  7683. end;
  7684.  
  7685.  
  7686. procedure reveal_exits(var one: boolean);
  7687. var
  7688.     retry,i: integer;
  7689.  
  7690. begin
  7691.     if debug then
  7692.         writeln('%revealing exits');
  7693.     one := false;
  7694.     retry := 1;
  7695.  
  7696.     repeat
  7697.         retry := retry + 1;
  7698.         i := (rnd100 mod maxexit) + 1;  { a random exit }
  7699.         if (here.exits[i].hidden <> 0) and (not found_exit[i]) then begin
  7700.             one := true;
  7701.             found_exit[i] := true;    { mark exit as found }
  7702.  
  7703.             if here.exits[i].hidden = DEFAULT_LINE then begin
  7704.                 if here.exits[i].alias = '' then
  7705.                     writeln('You''ve found a hidden exit: ',direct[i],'.')
  7706.                 else
  7707.                     writeln('You''ve found a hidden exit: ',here.exits[i].alias,'.');
  7708.             end else
  7709.                 print_desc(here.exits[i].hidden);
  7710.         end;
  7711.     until (retry > 4) or (one);
  7712. end;
  7713.  
  7714.  
  7715. procedure do_search(s: string);
  7716. var
  7717.     chance: integer;
  7718.     found,dummy: boolean;
  7719.  
  7720. begin
  7721.     if checkhide then begin
  7722.         chance := rnd100;
  7723.         found := false;
  7724.         dummy := false;
  7725.  
  7726.         if chance in [1..20] then
  7727.             reveal_objects(found)
  7728.         else if chance in [21..40] then
  7729.             reveal_exits(found)
  7730.         else if chance in [41..60] then
  7731.             reveal_people(dummy);
  7732.  
  7733.         if found then begin
  7734.             log_event(myslot,E_FOUND,0,0);
  7735.         end else if not(dummy) then begin
  7736.             log_event(myslot,E_SEARCH,0,0);
  7737.             writeln('You haven''t found anything.');
  7738.         end;
  7739.     end;
  7740. end;
  7741.  
  7742. procedure do_unhide(s: string);
  7743.  
  7744. begin
  7745.     if s = '' then begin
  7746.         if hiding then begin
  7747.             hiding := false;
  7748.             log_event(myslot,E_UNHIDE,0,0);
  7749.             getroom;
  7750.             here.people[myslot].hiding := 0;
  7751.             putroom;
  7752.             writeln('You are no longer hiding.');
  7753.         end else
  7754.             writeln('You were not hiding.');
  7755.     end;
  7756. end;
  7757.  
  7758.  
  7759. procedure do_hide(s: string);
  7760. var
  7761.     slot,n: integer;
  7762.     founddsc: integer;
  7763.     tmp: string;
  7764.  
  7765. begin
  7766.     gethere;
  7767.     if s = '' then begin    { hide yourself }
  7768.  
  7769.             { don't let them hide (or hide better) if people
  7770.               that they can see are in the room.  Note that the
  7771.               use of n_can_see instead of find_numpeople will
  7772.               let them hide if other people are hidden in the
  7773.               room that they have not seen.  The previously hidden
  7774.               people will see them hide }
  7775.  
  7776.         if n_can_see > 0 then begin
  7777.             if hiding then
  7778.                 writeln('You can''t hide any better with people in the room.')
  7779.             else
  7780.                 writeln('You can''t hide when people are watching you.');
  7781.         end else if (rnd100 > 25) then begin
  7782.             if here.people[myslot].hiding >= 4 then
  7783.                 writeln('You''re pretty well hidden now.  I don''t think you could be any less visible.')
  7784.             else begin
  7785.                 getroom;
  7786.                 here.people[myslot].hiding := 
  7787.                         here.people[myslot].hiding + 1;
  7788.                 putroom;
  7789.                 if hiding then begin
  7790.                     log_event(myslot,E_NOISES,rnd100,0);
  7791.                     writeln('You''ve managed to hide yourself a little better.');
  7792.                 end else begin
  7793.                     log_event(myslot,E_IHID,0,0);
  7794.                     writeln('You''ve hidden yourself from view.');
  7795.                     hiding := true;
  7796.                 end;
  7797.             end;
  7798.         end else begin { unsuccessful }
  7799.             if hiding then
  7800.                 writeln('You could not find a better hiding place.')
  7801.             else
  7802.                 writeln('You could not find a good hiding place.');
  7803.         end;
  7804.     end else begin    { Hide an object }
  7805.         if parse_obj(n,s) then begin
  7806.             if obj_here(n) then begin
  7807.                 writeln('Enter the description the player will see when the object is found:');
  7808.                 writeln('(if no description is given a default will be supplied)');
  7809.                 writeln;
  7810.                 writeln('[ Editing the "object found" description ]');
  7811.                 founddsc := 0;
  7812.                 if edit_desc(founddsc) then ;
  7813.                 if founddsc = 0 then
  7814.                     founddsc := DEFAULT_LINE;
  7815.  
  7816.                 getroom;
  7817.                 slot := find_obj(n);
  7818.                 here.objhide[slot] := founddsc;
  7819.                 putroom;
  7820.  
  7821.                 tmp := obj_part(n);
  7822.                 log_event(myslot,E_HIDOBJ,0,0,tmp);
  7823.                 writeln('You have hidden ',tmp,'.');
  7824.             end else if obj_hold(n) then begin
  7825.                 writeln('You''ll have to put it down before it can be hidden.');
  7826.             end else
  7827.                 writeln('I see no such object here.');
  7828.         end else
  7829.             writeln('I see no such object here.');
  7830.     end;
  7831. end;
  7832.  
  7833.  
  7834. procedure do_punch(s: string);
  7835. var
  7836.     sock,n: integer;
  7837.  
  7838. begin
  7839.     if s <> '' then begin
  7840.         if parse_pers(n,s) then begin
  7841.             if n = myslot then
  7842.                 writeln('Self-abuse will not be tolerated in the Monster universe.')
  7843.             else if protected(n) then begin
  7844.                 log_event(myslot,E_TRYPUNCH,n,0);
  7845.                 writeln('A mystic shield of force prevents you from attacking.');
  7846.             end else if here.people[n].username = MM_userid then begin
  7847.                 log_event(myslot,E_TRYPUNCH,n,0);
  7848.                 writeln('You can''t punch the Monster Manager.');
  7849.             end else begin
  7850.                 if hiding then begin
  7851.                     hiding := false;
  7852.  
  7853.                     getroom;
  7854.                     here.people[myslot].hiding := 0;
  7855.                     putroom;
  7856.  
  7857.                     log_event(myslot,E_HIDEPUNCH,n,0);
  7858.                     writeln('You pounce unexpectedly on ',here.people[n].name,'!');
  7859.                 end else begin
  7860.                     sock := (rnd100 mod numpunches)+1;
  7861.                     log_event(myslot,E_PUNCH,n,sock);
  7862.                     put_punch(sock,here.people[n].name);
  7863.                 end;
  7864.                 wait(1+random*3);    { Ha ha ha }
  7865.             end;
  7866.         end else
  7867.             writeln('That person cannot be seen in this room.');
  7868.     end else
  7869.         writeln('To punch somebody, type PUNCH <personal name>.');
  7870. end;
  7871.  
  7872.  
  7873. { support for do_program (custom an object)
  7874.   Give the player a list of kinds of object he's allowed to make his object
  7875.   and update it }
  7876.  
  7877. procedure prog_kind(objnum: integer);
  7878. var
  7879.     n: integer;
  7880.     s: string;
  7881.  
  7882. begin
  7883.     writeln('Select the type of your object:');
  7884.     writeln;
  7885.     writeln('0    Ordinary object (good for door keys)');
  7886.     writeln('1    Weapon');
  7887.     writeln('2    Armor');
  7888.     writeln('3    Exit thruster');
  7889.  
  7890.     if privd then begin
  7891.     writeln;
  7892.     writeln('100    Bag');
  7893.     writeln('101    Crystal Ball');
  7894.     writeln('102    Wand of Power');
  7895.     writeln('103    Hand of Glory');
  7896.     end;
  7897.     writeln;
  7898.     grab_line('Which kind? ',s);
  7899.  
  7900.     if isnum(s) then begin
  7901.         n := number(s);
  7902.         if (n > 100) and (privd) then
  7903.             writeln('Out of range.')
  7904.         else if n in [0..3,100..103] then begin
  7905.             getobj(objnum);
  7906.             obj.kind := n;
  7907.             putobj;
  7908.             writeln('Object updated.');
  7909.         end else
  7910.             writeln('Out of range.');
  7911.     end;
  7912. end;
  7913.  
  7914.  
  7915.  
  7916. { support for do_program (custom an object)
  7917.   Based on the kind it is allow the
  7918.   user to set the various parameters for the effects associated with that
  7919.   kind }
  7920.  
  7921. procedure prog_obj(objnum: integer);
  7922.  
  7923. begin
  7924. end;
  7925.  
  7926.  
  7927. procedure show_kind(p: integer);
  7928.  
  7929. begin
  7930.     case p of
  7931.         0: writeln('Ordinary object');
  7932.         1: writeln('Weapon');
  7933.         2: writeln('Armor');
  7934.         100: writeln('Bag');
  7935.         101: writeln('Crystal Ball');
  7936.         102: writeln('Wand of Power');
  7937.         103: writeln('Hand of Glory');
  7938.         otherwise writeln('Bad object type');
  7939.     end;
  7940. end;
  7941.  
  7942.  
  7943. procedure obj_view(objnum: integer);
  7944.  
  7945. begin
  7946.     writeln;
  7947.     getobj(objnum);
  7948.     freeobj;
  7949.     getobjown;
  7950.     freeobjown;
  7951.     writeln('Object name:    ',obj.oname);
  7952.     writeln('Owner:          ',objown.idents[objnum]);
  7953.     writeln;
  7954.     show_kind(obj.kind);
  7955.     writeln;
  7956.  
  7957.     if obj.linedesc = 0 then
  7958.         writeln('There is a(n) # here')
  7959.     else
  7960.         print_line(obj.linedesc);
  7961.  
  7962.     if obj.examine = 0 then
  7963.         writeln('No inspection description set')
  7964.     else
  7965.         print_desc(obj.examine);
  7966.  
  7967. {    writeln('Worth (in points) of this object: ',obj.worth:1);    }
  7968.     writeln('Number in existence: ',obj.numexist:1);
  7969.     writeln;
  7970. end;
  7971.  
  7972.  
  7973. procedure program_help;
  7974.  
  7975. begin
  7976.     writeln;
  7977.     writeln('A    "a", "an", "some", etc.');
  7978.     writeln('D    Edit a Description of the object');
  7979.     writeln('F    Edit the GET failure message');
  7980.     writeln('G    Set the object required to pick up this object');
  7981.     writeln('1    Set the get success message');
  7982.     writeln('K    Set the Kind of object this is');
  7983.     writeln('L    Edit the label description ("There is a ... here.")');
  7984.     writeln('P    Program the object based on the kind it is');
  7985.     writeln('R    Rename the object');
  7986.     writeln('S    Toggle the sticky bit');
  7987.     writeln;
  7988.     writeln('U    Set the object required for use');
  7989.     writeln('2    Set the place required for use');
  7990.     writeln('3    Edit the use failure description');
  7991.     writeln('4    Edit the use success description');
  7992.     writeln('V    View attributes of this object');
  7993.     writeln;
  7994.     writeln('X    Edit the extra description');
  7995.     writeln('5    Edit extra desc #2');
  7996.     writeln('E    Exit (same as Quit)');
  7997.     writeln('Q    Quit (same as Exit)');
  7998.     writeln('?    This list');
  7999.     writeln;
  8000. end;
  8001.  
  8002.  
  8003. procedure do_program;    { (objnam: string);  declared forward }
  8004. var
  8005.     prompt: string;
  8006.     done : boolean;
  8007.     s: string;
  8008.     objnum: integer;
  8009.     n: integer;
  8010.     newdsc: integer;
  8011.  
  8012. begin
  8013.     gethere;
  8014.     if checkhide then begin
  8015.     if length(objnam) = 0 then begin
  8016.         writeln('To program an object, type PROGRAM <object name>.');
  8017.     end else if lookup_obj(objnum,objnam) then begin
  8018.     if not is_owner(location,TRUE) then begin
  8019.         writeln('You may only work on your objects when you are in one of your own rooms.');
  8020.     end else if obj_owner(objnum) then begin
  8021.         log_action(e_program,0);
  8022.         writeln;
  8023.         writeln('Customizing object');
  8024.         writeln('If you would rather be customizing an EXIT, type CUSTOM <direction of exit>');
  8025.         writeln('If you would rather be customizing this room, type CUSTOM');
  8026.         writeln;
  8027.         getobj(objnum);
  8028.         freeobj;
  8029.         prompt := 'Custom object> ';
  8030.         done := false;
  8031.         repeat
  8032.             repeat
  8033.                 grab_line(prompt,s);
  8034.                 s := slead(s);
  8035.             until length(s) > 0;
  8036.             s := lowcase(s);
  8037.             case s[1] of
  8038.                 '?','h': program_help;
  8039.                 'q','e': done := true;
  8040.                 'v': obj_view(objnum);
  8041.                 'r': do_objrename(objnum);
  8042.                 'g': begin
  8043.                     writeln('Enter * for no object');
  8044.                     grab_line('Object required for GET? ',s);
  8045.                     if s = '*' then begin
  8046.                         getobj(objnum);
  8047.                         obj.getobjreq := 0;
  8048.                         putobj;
  8049.                     end else if lookup_obj(n,s) then begin
  8050.                         getobj(objnum);
  8051.                         obj.getobjreq := n;
  8052.                         putobj;
  8053.                         writeln('Object modified.');
  8054.                     end else
  8055.                         writeln('No such object.');
  8056.                      end;
  8057.                 'u': begin
  8058.                     writeln('Enter * for no object');
  8059.                     grab_line('Object required for USE? ',s);
  8060.                     if s = '*' then begin
  8061.                         getobj(objnum);
  8062.                         obj.useobjreq := 0;
  8063.                         putobj;
  8064.                     end else if lookup_obj(n,s) then begin
  8065.                         getobj(objnum);
  8066.                         obj.useobjreq := n;
  8067.                         putobj;
  8068.                         writeln('Object modified.');
  8069.                     end else
  8070.                         writeln('No such object.');
  8071.                      end;
  8072.                 '2': begin
  8073.                     writeln('Enter * for no special place');
  8074.                     grab_line('Place required for USE? ',s);
  8075.                     if s = '*' then begin
  8076.                         getobj(objnum);
  8077.                         obj.uselocreq := 0;
  8078.                         putobj;
  8079.                     end else if lookup_room(n,s) then begin
  8080.                         getobj(objnum);
  8081.                         obj.uselocreq := n;
  8082.                         putobj;
  8083.                         writeln('Object modified.');
  8084.                     end else
  8085.                         writeln('No such object.');
  8086.                      end;
  8087.                 's': begin
  8088.                     getobj(objnum);
  8089.                     obj.sticky := not(obj.sticky);
  8090.                     putobj;
  8091.                     if obj.sticky then
  8092.                         writeln('The object will not be takeable.')
  8093.                     else
  8094.                         writeln('The object will be takeable.');
  8095.                      end;
  8096.                 'a': begin
  8097.                     writeln;
  8098.                     writeln('Select the article for your object:');
  8099.                     writeln;
  8100.                     writeln('0)    None                ex: " You have taken Excalibur "');
  8101.                     writeln('1)    "a"                 ex: " You have taken a small box "');
  8102.                     writeln('2)    "an"                ex: " You have taken an empty bottle "');
  8103.                     writeln('3)    "some"              ex: " You have picked up some jelly beans "');
  8104.                     writeln('4)     "the"               ex: " You have picked up the Scepter of Power"');
  8105.                     writeln;
  8106.                     grab_line('? ',s);
  8107.                     if isnum(s) then begin
  8108.                         n := number(s);
  8109.                         if n in [0..4] then begin
  8110.                             getobj(objnum);
  8111.                             obj.particle := n;
  8112.                             putobj;
  8113.                         end else
  8114.                             writeln('Out of range.');
  8115.                     end else
  8116.                         writeln('No changes.');
  8117.                      end;
  8118.                 'k': begin
  8119.                     prog_kind(objnum);
  8120.                      end;
  8121.                 'p': begin
  8122.                     prog_obj(objnum);
  8123.                      end;
  8124.                 'd': begin
  8125.                     newdsc := obj.examine;
  8126.                     writeln('[ Editing the description of the object ]');
  8127.                     if edit_desc(newdsc) then begin
  8128.                         getobj(objnum);
  8129.                         obj.examine := newdsc;
  8130.                         putobj;
  8131.                     end;
  8132.                      end;
  8133.                 'x': begin
  8134.                     newdsc := obj.d1;
  8135.                     writeln('[ Editing extra description #1 ]');
  8136.                     if edit_desc(newdsc) then begin
  8137.                         getobj(objnum);
  8138.                         obj.d1 := newdsc;
  8139.                         putobj;
  8140.                     end;
  8141.                      end;
  8142.                 '5': begin
  8143.                     newdsc := obj.d2;
  8144.                     writeln('[ Editing extra description #2 ]');
  8145.                     if edit_desc(newdsc) then begin
  8146.                         getobj(objnum);
  8147.                         obj.d2 := newdsc;
  8148.                         putobj;
  8149.                     end;
  8150.                      end;
  8151.                 'f': begin
  8152.                     newdsc := obj.getfail;
  8153.                     writeln('[ Editing the get failure description ]');
  8154.                     if edit_desc(newdsc) then begin
  8155.                         getobj(objnum);
  8156.                         obj.getfail := newdsc;
  8157.                         putobj;
  8158.                     end;
  8159.                      end;
  8160.                 '1': begin
  8161.                     newdsc := obj.getsuccess;
  8162.                     writeln('[ Editing the get success description ]');
  8163.                     if edit_desc(newdsc) then begin
  8164.                         getobj(objnum);
  8165.                         obj.getsuccess := newdsc;
  8166.                         putobj;
  8167.                     end;
  8168.                      end;
  8169.                 '3': begin
  8170.                     newdsc := obj.usefail;
  8171.                     writeln('[ Editing the use failure description ]');
  8172.                     if edit_desc(newdsc) then begin
  8173.                         getobj(objnum);
  8174.                         obj.usefail := newdsc;
  8175.                         putobj;
  8176.                     end;
  8177.                      end;
  8178.                 '4': begin
  8179.                     newdsc := obj.usesuccess;
  8180.                     writeln('[ Editing the use success description ]');
  8181.                     if edit_desc(newdsc) then begin
  8182.                         getobj(objnum);
  8183.                         obj.usesuccess := newdsc;
  8184.                         putobj;
  8185.                     end;
  8186.                      end;
  8187.                 'l': begin
  8188.                     writeln('Enter a one line description of what the object will look like in any room.');
  8189.                     writeln('Example: "There is an as unyet described object here."');
  8190.                     writeln;
  8191.                     getobj(objnum);
  8192.                     freeobj;
  8193.                     n := obj.linedesc;
  8194.                     make_line(n);
  8195.                     getobj(objnum);
  8196.                     obj.linedesc := n;
  8197.                     putobj;
  8198.                      end;
  8199.                 otherwise writeln('-- Bad command, type ? for a list');
  8200.             end;
  8201.         until done;
  8202.         log_event(myslot,E_OBJDONE,objnum,0);
  8203.  
  8204.     end else
  8205.         writeln('You are not allowed to program that object.');
  8206.     end else
  8207.         writeln('There is no object by that name.');
  8208.     end;
  8209. end;
  8210.  
  8211.  
  8212. { returns TRUE if anything was actually dropped }
  8213. function drop_everything;
  8214. { forward function drop_everything(pslot: integer := 0): boolean; }
  8215. var
  8216.     i: integer;
  8217.     slot: integer;
  8218.     didone: boolean;
  8219.     theobj: integer;
  8220.     tmp: string;
  8221.  
  8222. begin
  8223.     if pslot = 0 then
  8224.         pslot := myslot;
  8225.  
  8226.     gethere;
  8227.     didone := false;
  8228.  
  8229.     mywield := 0;
  8230.     mywear := 0;
  8231.  
  8232.     for i := 1 to maxhold do begin
  8233.         if here.people[pslot].holding[i] <> 0 then begin
  8234.             didone := true;
  8235.             theobj := here.people[pslot].holding[i];
  8236.             slot := find_hold(theobj,pslot);
  8237.             if place_obj(theobj,TRUE) then begin
  8238.                 drop_obj(slot,pslot);
  8239.             end else begin    { no place to put it, it's lost .... }
  8240.                 getobj(theobj);
  8241.                 obj.numexist := obj.numexist - 1;
  8242.                 putobj;
  8243.                 tmp := obj.oname;
  8244.                 writeln('The ',tmp,' was lost.');
  8245.             end;
  8246.         end;
  8247.     end;
  8248.  
  8249.     drop_everything := didone;
  8250. end;
  8251.  
  8252. procedure do_endplay(lognum: integer;ping:boolean := FALSE);
  8253.  
  8254. { If update is true do_endplay will update the "last play" date & time
  8255.   we don't want to do this if this endplay is called from a ping }
  8256.  
  8257. begin
  8258.     if not(ping) then begin
  8259.             { Set the "last date & time of play" }
  8260.         getdate;
  8261.         adate.idents[lognum] := sysdate + ' ' + systime;
  8262.         putdate;
  8263.     end;
  8264.  
  8265.  
  8266.     { Put the player to sleep.  Don't delete his information,
  8267.       so it can be restored the next time they play. }
  8268.  
  8269.     getindex(I_ASLEEP);
  8270.     indx.free[lognum] := true;    { Yes, I'm asleep }
  8271.     putindex;
  8272. end;
  8273.  
  8274.  
  8275. function check_person(n: integer;id: string):boolean;
  8276.  
  8277. begin
  8278.     inmem := false;
  8279.     gethere;
  8280.     if here.people[n].username = id then
  8281.         check_person := true
  8282.     else
  8283.         check_person := false;
  8284. end;
  8285.  
  8286.  
  8287. function nuke_person(n: integer;id: string): boolean;
  8288. var
  8289.     lognum: integer;
  8290.     tmp: string;
  8291.  
  8292. begin
  8293.     getroom;
  8294.     if here.people[n].username = id then begin
  8295.  
  8296.             { drop everything they're carrying }
  8297.         drop_everything(n);
  8298.  
  8299.         tmp := here.people[n].username;
  8300.             { we'll need this for do_endplay }
  8301.  
  8302.             { Remove the person from the room }
  8303.         here.people[n].kind := 0;
  8304.         here.people[n].username := '';
  8305.         here.people[n].name := '';
  8306.         putroom;
  8307.  
  8308.             { update the log entries for them }
  8309.             { but first we have to find their log number
  8310.               (mylog for them).  We can do this with a lookup_user
  8311.               give the userid we got above }
  8312.  
  8313.         if lookup_user(lognum,tmp) then begin
  8314.             do_endplay(lognum,TRUE);
  8315.                 { TRUE tells do_endplay not to update the
  8316.                   "time of last play" information 'cause we
  8317.                   don't know how long the "zombie" has been
  8318.                   there. }
  8319.         end else
  8320.             writeln('%error in nuke_person; can''t fing their log number; notify the Monster Manager');
  8321.  
  8322.         nuke_person := true;
  8323.     end else begin
  8324.         freeroom;
  8325.         nuke_person := false;
  8326.     end;
  8327. end;
  8328.  
  8329.  
  8330. function ping_player(n:integer;silent: boolean := false): boolean;
  8331. var
  8332.     retry: integer;
  8333.     id: string;
  8334.     idname: string;
  8335.  
  8336. begin
  8337.     ping_player := false;
  8338.  
  8339.     id := here.people[n].username;
  8340.     idname := here.people[n].name;
  8341.  
  8342.     retry := 0;
  8343.     ping_answered := false;
  8344.  
  8345.     repeat
  8346.         retry := retry + 1;
  8347.         if not(silent) then
  8348.             writeln('Sending ping # ',retry:1,' to ',idname,' . . .');
  8349.  
  8350.         log_event(myslot,E_PING,n,0,myname);
  8351.         wait(1);
  8352.         checkevents(TRUE);
  8353.                 { TRUE = don't reprint prompt }
  8354.  
  8355.         if not(ping_answered) then
  8356.             if check_person(n,id) then begin
  8357.                 wait(1);
  8358.                 checkevents(TRUE);
  8359.             end else
  8360.                 ping_answered := true;
  8361.  
  8362.         if not(ping_answered) then
  8363.             if check_person(n,id) then begin
  8364.                 wait(1);
  8365.                 checkevents(TRUE);
  8366.             end else
  8367.                 ping_answered := true;
  8368.  
  8369.     until (retry >= 3) or ping_answered;
  8370.  
  8371.     if not(ping_answered) then begin
  8372.         if not(silent) then
  8373.             writeln('That person is not responding to your pings . . .');
  8374.  
  8375.         if nuke_person(n,id) then begin
  8376.             ping_player := true;
  8377.             if not(silent) then
  8378.                 writeln(idname,' shimmers and vanishes from sight.');
  8379.             log_event(myslot,E_PINGONE,n,0,idname);
  8380.         end else
  8381.             if not(silent) then
  8382.                 writeln('That person is not a zombie after all.');
  8383.     end else
  8384.         if not(silent) then
  8385.             writeln('That person is alive and well.');
  8386. end;
  8387.  
  8388.  
  8389. procedure do_ping(s: string);
  8390. var
  8391.     n: integer;
  8392.     dummy: boolean;
  8393.  
  8394. begin
  8395.     if s <> '' then begin
  8396.         if parse_pers(n,s) then begin
  8397.             if n = myslot then
  8398.                 writeln('Don''t ping yourself.')
  8399.             else
  8400.                 dummy := ping_player(n);
  8401.         end else
  8402.             writeln('You see no person here by that name.');
  8403.     end else
  8404.         writeln('To see if someone is really alive, type PING <personal name>.');
  8405. end;
  8406.  
  8407. procedure list_get;
  8408. var
  8409.     first: boolean;
  8410.     i: integer;
  8411.  
  8412. begin
  8413.     first := true;
  8414.     for i := 1 to maxobjs do begin
  8415.         if (here.objs[i] <> 0) and
  8416.            (here.objhide[i] = 0) then begin
  8417.             if first then begin
  8418.                 writeln('Objects that you see here:');
  8419.                 first := false;
  8420.             end;
  8421.             writeln('   ',obj_part(here.objs[i]));
  8422.         end;
  8423.     end;
  8424.     if first then
  8425.         writeln('There is nothing you see here that you can get.');
  8426. end;
  8427.  
  8428.  
  8429.  
  8430. { print the get success message for object number n }
  8431.  
  8432. procedure p_getsucc(n: integer);
  8433.  
  8434. begin
  8435.     { we assume getobj has already been done }
  8436.     if (obj.getsuccess = 0) or (obj.getsuccess = DEFAULT_LINE) then
  8437.         writeln('Taken.')
  8438.     else
  8439.         print_desc(obj.getsuccess);
  8440. end;
  8441.  
  8442.  
  8443. procedure do_meta_get(n: integer);
  8444. var
  8445.     slot: integer;
  8446.  
  8447. begin
  8448.     if obj_here(n) then begin
  8449.         if can_hold then begin
  8450.             slot := find_obj(n);
  8451.             if take_obj(n,slot) then begin
  8452.                 hold_obj(n);
  8453.                 log_event(myslot,E_GET,0,0,
  8454. { >>> }        myname + ' has picked up ' + obj_part(n) + '.');
  8455.                 p_getsucc(n);
  8456.             end else
  8457.                 writeln('Someone got to it before you did.');
  8458.         end else
  8459.             writeln('Your hands are full.  You''ll have to drop something you''re carrying first.');
  8460.     end else if obj_hold(n) then
  8461.         writeln('You''re already holding that item.')
  8462.     else
  8463.         writeln('That item isn''t in an obvious place.');
  8464. end;
  8465.  
  8466.  
  8467. procedure do_get(s: string);
  8468. var
  8469.     n: integer;
  8470.     ok: boolean;
  8471.  
  8472. begin
  8473.     if s = '' then begin
  8474.         list_get;
  8475.     end else if parse_obj(n,s,TRUE) then begin
  8476.         getobj(n);
  8477.         freeobj;
  8478.         ok := true;
  8479.  
  8480.         if obj.sticky then begin
  8481.             ok := false;
  8482.             log_event(myslot,E_FAILGET,n,0);
  8483.             if (obj.getfail = 0) or (obj.getfail = DEFAULT_LINE) then
  8484.                 writeln('You can''t take ',obj_part(n,FALSE),'.')
  8485.             else
  8486.                 print_desc(obj.getfail);
  8487.         end else if obj.getobjreq > 0 then begin
  8488.             if not(obj_hold(obj.getobjreq)) then begin
  8489.                 ok := false;
  8490.                 log_event(myslot,E_FAILGET,n,0);
  8491.                 if (obj.getfail = 0) or (obj.getfail = DEFAULT_LINE) then
  8492.                     writeln('You''ll need something first to get the ',obj_part(n,FALSE),'.')
  8493.                 else
  8494.                     print_desc(obj.getfail);
  8495.             end;
  8496.         end;
  8497.  
  8498.         if ok then
  8499.             do_meta_get(n);        { get the object }
  8500.  
  8501.     end else if lookup_detail(n,s) then begin
  8502.             writeln('That detail of this room is here for the enjoyment of all Monster players,');
  8503.             writeln('and may not be taken.');
  8504.     end else
  8505.         writeln('There is no object here by that name.');
  8506. end;
  8507.  
  8508.  
  8509. procedure do_drop(s: string);
  8510. var
  8511.     slot,n: integer;
  8512.  
  8513. begin
  8514.     if s = '' then begin
  8515.         writeln('To drop an object, type DROP <object name>.');
  8516.         writeln('To see what you are carrying, type INV (inventory).');
  8517.     end else if parse_obj(n,s) then begin
  8518.         if obj_hold(n) then begin
  8519.             getobj(n);
  8520.             freeobj;
  8521.             if obj.sticky then
  8522.                 writeln('You can''t drop sticky objects.')
  8523.             else if can_drop then begin
  8524.                 slot := find_hold(n);
  8525.                 if place_obj(n) then begin
  8526.                     drop_obj(slot);
  8527.                     log_event(myslot,E_DROP,0,n,
  8528.                         myname + ' has dropped '+obj_part(n) + '.');
  8529.  
  8530.                     if mywield = n then begin
  8531.                         mywield := 0;
  8532.                         getroom;
  8533.                         here.people[myslot].wielding := 0;
  8534.                         putroom;
  8535.                     end;
  8536.                     if mywear = n then begin
  8537.                         mywear := 0;
  8538.                         getroom;
  8539.                         here.people[myslot].wearing := 0;
  8540.                         putroom;
  8541.                     end;
  8542.                 end else
  8543.                     writeln('Someone took the spot where your were going to drop it.');
  8544.             end else
  8545.                 writeln('It is too cluttered here.  Find somewhere else to drop your things.');
  8546.         end else begin
  8547.             writeln('You''re not holding that item.  To see what you''re holding, type INV.');
  8548.         end;
  8549.     end else
  8550.         writeln('You''re not holding that item.  To see what you''re holding, type INVENTORY.');
  8551. end;
  8552.  
  8553.  
  8554. procedure do_inv(s: string);
  8555. var
  8556.     first: boolean;
  8557.     i,n: integer;
  8558.     objnum: integer;
  8559.  
  8560. begin
  8561.     gethere;
  8562.     if s = '' then begin
  8563.         noisehide(50);
  8564.         first := true;
  8565.         log_event(myslot,E_INVENT,0,0);
  8566.         for i := 1 to maxhold do begin
  8567.             objnum := here.people[myslot].holding[i];
  8568.             if objnum <> 0 then begin
  8569.                 if first then begin
  8570.                     writeln('You are holding:');
  8571.                     first := false;
  8572.                 end;
  8573.                 writeln('   ',obj_part(objnum));
  8574.             end;
  8575.         end;
  8576.         if first then
  8577.             writeln('You are empty handed.');
  8578.     end else if parse_pers(n,s) then begin
  8579.         first := true;
  8580.         log_event(myslot,E_LOOKYOU,n,0);
  8581.         for i := 1 to maxhold do begin
  8582.             objnum := here.people[n].holding[i];
  8583.             if objnum <> 0 then begin
  8584.                 if first then begin
  8585.                     writeln(here.people[n].name,' is holding:');
  8586.                     first := false;
  8587.                 end;
  8588.                 writeln('   ',objnam.idents[ objnum ]);
  8589.             end;
  8590.         end;
  8591.         if first then
  8592.             writeln(here.people[n].name,' is empty handed.');
  8593.     end else
  8594.         writeln('To see what someone else is carrying, type INV <personal name>.');
  8595. end;
  8596.  
  8597.  
  8598. { translate a personal name into a real userid on request }
  8599.  
  8600. procedure do_whois(s: string);
  8601. var
  8602.     n: integer;
  8603.  
  8604. begin
  8605.     if lookup_pers(n,s) then begin
  8606.         getuser;
  8607.         freeuser;
  8608. {        getpers;
  8609.         freepers;    ! Already done in lookup_pers !        }
  8610.  
  8611.         writeln(pers.idents[n],' is ',user.idents[n],'.');
  8612.     end else
  8613.         writeln('There is no one playing with that personal name.');
  8614. end;
  8615.  
  8616.  
  8617. procedure do_players(s: string);
  8618. var
  8619.     i,j: integer;
  8620.     tmpasleep: indexrec;
  8621.     where_they_are: intrec;
  8622.  
  8623. begin
  8624.     log_event(myslot,E_PLAYERS,0,0);
  8625.     getindex(I_ASLEEP);    { Rec of bool; False if playing now }
  8626.     freeindex;
  8627.     tmpasleep := indx;
  8628.  
  8629.     getindex(I_PLAYER);    { Rec of valid player log records  }
  8630.     freeindex;        { False if a valid player log }
  8631.  
  8632.     getuser;        { Corresponding userids of players }
  8633.     freeuser;
  8634.  
  8635.     getpers;        { Personal names of players }
  8636.     freepers;
  8637.  
  8638.     getdate;        { date of last play }
  8639.     freedate;
  8640.  
  8641.     if privd then begin
  8642.         getint(N_LOCATION);
  8643.         freeint;
  8644.         where_they_are := anint;
  8645.  
  8646.         getnam;
  8647.         freenam;
  8648.     end;
  8649.  
  8650.     getint(N_SELF);
  8651.     freeint;
  8652.  
  8653.     writeln;
  8654.     writeln('Userid          Personal Name              Last Play');
  8655.     for i := 1 to maxplayers do begin
  8656.         if not(indx.free[i]) then begin
  8657.             write(user.idents[i]);
  8658.             for j := length(user.idents[i]) to 15 do
  8659.                 write(' ');
  8660.             write(pers.idents[i]);
  8661.             for j := length(pers.idents[i]) to 21 do
  8662.                 write(' ');
  8663.  
  8664.             if tmpasleep.free[i] then begin
  8665.                 write(adate.idents[i]);
  8666.                 if length(adate.idents[i]) < 19 then
  8667.                     for j := length(adate.idents[i]) to 18 do
  8668.                         write(' ');
  8669.             end else
  8670.                 write('   -playing now-   ');
  8671.  
  8672.             if (anint.int[i] <> 0) and (anint.int[i] <> DEFAULT_LINE) then
  8673.                 write(' * ')
  8674.             else
  8675.                 write('   ');
  8676.  
  8677.             if privd then begin
  8678.                 write(nam.idents[ where_they_are.int[i] ]);
  8679.             end;
  8680.             writeln;
  8681.         end;
  8682.     end;
  8683.     writeln;
  8684. end;
  8685.  
  8686.  
  8687. procedure do_self(s: string);
  8688. var
  8689.     n: integer;
  8690.  
  8691. begin
  8692.     if length(s) = 0 then begin
  8693.         log_action(c_self,0);
  8694.         writeln('[ Editing your self description ]');
  8695.         if edit_desc(myself) then begin
  8696.             getroom;
  8697.             here.people[myslot].self := myself;
  8698.             putroom;
  8699.             getint(N_SELF);
  8700.             anint.int[mylog] := myself;
  8701.             putint;
  8702.             log_event(myslot,E_SELFDONE,0,0);
  8703.         end;
  8704.     end else if lookup_pers(n,s) then begin
  8705.         getint(N_SELF);
  8706.         freeint;
  8707.         if (anint.int[n] = 0) or (anint.int[n] = DEFAULT_LINE) then
  8708.             writeln('That person has not made a self-description.')
  8709.         else begin
  8710.             print_desc(anint.int[n]);
  8711.             log_event(myslot,E_VIEWSELF,0,0,pers.idents[n]);
  8712.         end;
  8713.     end else
  8714.         writeln('There is no person by that name.');
  8715. end;
  8716.  
  8717.  
  8718. procedure do_health(s: string);
  8719.  
  8720. begin
  8721.     write('You ');
  8722.     case myhealth of
  8723.         9: writeln('are in exceptional health.');
  8724.         8: writeln('are in better than average condition.');
  8725.         7: writeln('are in perfect health.');
  8726.         6: writeln('feel a little bit dazed.');
  8727.         5: writeln('have some minor cuts and abrasions.');
  8728.         4: writeln('have some wounds, but are still fairly strong.');
  8729.         3: writeln('are suffering from some serious wounds.'); 
  8730.         2: writeln('are very badly wounded.');
  8731.         1: writeln('have many serious wounds, and are near death.');
  8732.         0: writeln('are dead.');
  8733.         otherwise writeln('don''t seem to be in any condition at all.');
  8734.     end;
  8735. end;
  8736.  
  8737.  
  8738. procedure crystal_look(chill_msg: integer);
  8739. var
  8740.     numobj,numppl,numsee: integer;
  8741.     i: integer;
  8742.     yes: boolean;
  8743.  
  8744. begin
  8745.     writeln;
  8746.     print_desc(here.primary);
  8747.     log_event(0,E_CHILL,chill_msg,0,'',here.locnum);
  8748.     numppl := find_numpeople;
  8749.     numsee := n_can_see + 1;
  8750.  
  8751.     if numppl > numsee then
  8752.         writeln('Someone is hiding here.')
  8753.     else if numppl = 0 then begin
  8754.         writeln('Strange, empty shadows swirl before your eyes.');
  8755.     end;
  8756.     if rnd100 > 50 then
  8757.         people_header('at this place.')
  8758.     else case numppl of
  8759.             0: writeln('Vague empty forms drift through your view.');
  8760.             1: writeln('You can make out a shadowy figure here.');
  8761.             2: writeln('There are two dark figures here.');
  8762.             3: writeln('You can see the silhouettes of three people.');
  8763.             otherwise
  8764.                 writeln('Many dark figures can be seen here.');
  8765.     end;
  8766.  
  8767.     numobj := find_numobjs;
  8768.     if rnd100 > 50 then begin
  8769.         if rnd100 > 50 then
  8770.             show_objects
  8771.         else if numobj > 0 then
  8772.             writeln('Some objects are here.')
  8773.         else
  8774.             writeln('There are no objects here.');
  8775.     end else begin
  8776.         yes := false;
  8777.         for i := 1 to maxobjs do
  8778.             if here.objhide[i] <> 0 then
  8779.                 yes := true;
  8780.         if yes then
  8781.             writeln('Something is hidden here.');
  8782.     end;
  8783.     writeln;
  8784. end;
  8785.  
  8786.  
  8787. procedure use_crystal(objnum: integer);
  8788. var
  8789.     done: boolean;
  8790.     s: string;
  8791.     n: integer;
  8792.     done_msg,chill_msg: integer;
  8793.     tmp: string;
  8794.     i: integer;
  8795.  
  8796. begin
  8797.     if obj_hold(objnum) then begin
  8798.         log_action(e_usecrystal,0);
  8799.         getobj(objnum);
  8800.         freeobj;
  8801.         done_msg := obj.d1;
  8802.         chill_msg := obj.d2;
  8803.  
  8804.         grab_line('',s);
  8805.         if lookup_room(n,s) then begin
  8806.             gethere(n);
  8807.             crystal_look(chill_msg);
  8808.             done := false;
  8809.         end else
  8810.             done := true;
  8811.  
  8812.         while not(done) do begin
  8813.             grab_line('',s);
  8814.             if lookup_dir(n,s) then begin
  8815.                 if here.exits[n].toloc > 0 then begin
  8816.                     gethere(here.exits[n].toloc);
  8817.                     crystal_look(chill_msg);
  8818.                 end;
  8819.             end else begin
  8820.                 s := lowcase(s);
  8821.                 tmp := bite(s);
  8822.                 if tmp = 'poof' then begin
  8823.                     if lookup_room(n,s) then begin
  8824.                         gethere(n);
  8825.                         crystal_look(chill_msg);
  8826.                     end else
  8827.                         done := true;
  8828.                 end else if tmp = 'say' then begin
  8829.                     i := (rnd100 mod 4) + 1;
  8830.                     log_event(0,E_NOISE2,i,0,'',n);
  8831.                 end else
  8832.                     done := true;
  8833.             end;
  8834.         end;
  8835.  
  8836.         gethere;
  8837.         log_event(myslot,E_DONECRYSTALUSE,0,0);
  8838.         print_desc(done_msg);
  8839.     end else
  8840.         writeln('You must be holding it first.');
  8841. end;
  8842.  
  8843.  
  8844.  
  8845. procedure p_usefail(n: integer);
  8846.  
  8847. begin
  8848.     { we assume getobj has already been done }
  8849.     if (obj.usefail = 0) or (obj.usefail = DEFAULT_LINE) then
  8850.         writeln('It doesn''t work for some reason.')
  8851.     else
  8852.         print_desc(obj.usefail);
  8853. end;
  8854.  
  8855.  
  8856. procedure p_usesucc(n: integer);
  8857.  
  8858. begin
  8859.     { we assume getobj has already been done }
  8860.     if (obj.usesuccess = 0) or (obj.usesuccess = DEFAULT_LINE) then
  8861.         writeln('It seems to work, but nothing appears to happen.')
  8862.     else
  8863.         print_desc(obj.usesuccess);
  8864. end;
  8865.  
  8866.  
  8867. procedure do_use(s: string);
  8868. var
  8869.     n: integer;
  8870.  
  8871. begin
  8872.     if length(s) = 0 then
  8873.         writeln('To use an object, type USE <object name>')
  8874.     else if parse_obj(n,s) then begin
  8875.         getobj(n);
  8876.         freeobj;
  8877.  
  8878.         if (obj.useobjreq > 0) and not(obj_hold(obj.useobjreq)) then begin
  8879.             log_event(myslot,E_FAILUSE,n,0);
  8880.             p_usefail(n);
  8881.         end else if (obj.uselocreq > 0) and (location <> obj.uselocreq) then begin
  8882.             log_event(myslot,E_FAILUSE,n,0);
  8883.             p_usefail(n);
  8884.         end else begin
  8885.             p_usesucc(n);
  8886.             case obj.kind of
  8887.                 O_BLAND:;
  8888.                 O_CRYSTAL: use_crystal(n);
  8889.                 otherwise ;
  8890.             end;
  8891.         end;
  8892.     end else
  8893.         writeln('There is no such object here.');
  8894. end;
  8895.  
  8896.  
  8897. procedure do_whisper(s: string);
  8898. var
  8899.     n: integer;
  8900.  
  8901. begin
  8902.     if length(s) = 0 then begin
  8903.         writeln('To whisper to someone, type WHISPER <personal name>.');
  8904.     end else if parse_pers(n,s) then begin
  8905.         if n = myslot then
  8906.             writeln('You can''t whisper to yourself.')
  8907.         else begin
  8908.             grab_line('>> ',s);
  8909.             if length(s) > 0 then begin
  8910.                 nice_say(s);
  8911.                 log_event(myslot,E_WHISPER,n,0,s);
  8912.             end else
  8913.                 writeln('Nothing whispered.');
  8914.         end;
  8915.     end else
  8916.         writeln('No such person can be seen here.');
  8917. end;
  8918.  
  8919.  
  8920. procedure do_wield(s: string);
  8921. var
  8922.     tmp: string;
  8923.     slot,n: integer;
  8924.  
  8925. begin
  8926.     if length(s) = 0 then begin    { no parms means unwield }
  8927.         if mywield = 0 then
  8928.             writeln('You are not wielding anything.')
  8929.         else begin
  8930.             getobj(mywield);
  8931.             freeobj;
  8932.             tmp := obj.oname;
  8933.             log_event(myslot,E_UNWIELD,0,0,tmp);
  8934.             writeln('You are no longer wielding the ',tmp,'.');
  8935.  
  8936.             mywield := 0;
  8937.             getroom;
  8938.             here.people[mylog].wielding := 0;
  8939.             putroom;
  8940.         end;
  8941.     end else if parse_obj(n,s) then begin
  8942.         if mywield <> 0 then begin
  8943.             writeln('You are already wielding ',obj_part(mywield),'.');
  8944.         end else begin
  8945.             getobj(n);
  8946.             freeobj;
  8947.             tmp := obj.oname;
  8948.             if obj.kind = O_WEAPON then begin
  8949.                 if obj_hold(n) then begin
  8950.                     mywield := n;
  8951.                     getroom;
  8952.                     here.people[myslot].wielding := n;
  8953.                     putroom;
  8954.  
  8955.                     log_event(myslot,E_WIELD,0,0,tmp);
  8956.                     writeln('You are now wielding the ',tmp,'.');
  8957.                 end else
  8958.                     writeln('You must be holding it first.');
  8959.             end else
  8960.             writeln('That is not a weapon.');
  8961.         end;
  8962.     end else
  8963.         writeln('No such weapon can be seen here.');
  8964. end;
  8965.  
  8966.  
  8967. procedure do_wear(s: string);
  8968. var
  8969.     tmp: string;
  8970.     slot,n: integer;
  8971.  
  8972. begin
  8973.     if length(s) = 0 then begin    { no parms means unwield }
  8974.         if mywear = 0 then
  8975.             writeln('You are not wearing anything.')
  8976.         else begin
  8977.             getobj(mywear);
  8978.             freeobj;
  8979.             tmp := obj.oname;
  8980.             log_event(myslot,E_UNWEAR,0,0,tmp);
  8981.             writeln('You are no longer wearing the ',tmp,'.');
  8982.  
  8983.             mywear := 0;
  8984.             getroom;
  8985.             here.people[mylog].wearing := 0;
  8986.             putroom;
  8987.         end;
  8988.     end else if parse_obj(n,s) then begin
  8989.         getobj(n);
  8990.         freeobj;
  8991.         tmp := obj.oname;
  8992.         if (obj.kind = O_ARMOR) or (obj.kind = O_CLOAK) then begin
  8993.             if obj_hold(n) then begin
  8994.                 mywear := n;
  8995.                 getroom;
  8996.                 here.people[mylog].wearing := n;
  8997.                 putroom;
  8998.  
  8999.                 log_event(myslot,E_WEAR,0,0,tmp);
  9000.                 writeln('You are now wearing the ',tmp,'.');
  9001.             end else
  9002.                 writeln('You must be holding it first.');
  9003.         end else
  9004.             writeln('That cannot be worn.');
  9005.     end else
  9006.         writeln('No such thing can be seen here.');
  9007. end;
  9008.  
  9009.  
  9010. procedure do_brief;
  9011.  
  9012. begin
  9013.     brief := not(brief);
  9014.     if brief then
  9015.         writeln('Brief descriptions.')
  9016.     else
  9017.         writeln('Verbose descriptions.');
  9018. end;
  9019.  
  9020.  
  9021. function p_door_key(n: integer): string;
  9022.  
  9023. begin
  9024.     if n = 0 then
  9025.         p_door_key := '<none>'
  9026.     else
  9027.         p_door_key := objnam.idents[n];
  9028. end;
  9029.  
  9030.  
  9031.  
  9032. procedure anal_exit(dir: integer);
  9033.  
  9034. begin
  9035.     if (here.exits[dir].toloc = 0) and (here.exits[dir].kind <> 5) then
  9036.         { no exit here, don't print anything }
  9037.     else with here.exits[dir] do begin
  9038.         write(direct[dir]);
  9039.         if length(alias) > 0 then begin
  9040.             write('(',alias);
  9041.             if reqalias then
  9042.                 write(' required): ')
  9043.             else
  9044.                 write('): ');
  9045.         end else
  9046.             write(': ');
  9047.  
  9048.         if (toloc = 0) and (kind = 5) then
  9049.             write('accept, no exit yet')
  9050.         else if toloc > 0 then begin
  9051.             write('to ',nam.idents[toloc],', ');
  9052.             case kind of
  9053.                 0: write('no exit');
  9054.                 1: write('open passage');
  9055.                 2: write('door, key=',p_door_key(objreq));
  9056.                 3: write('~door, ~key=',p_door_key(objreq));
  9057.                 4: write('exit open randomly');
  9058.                 5: write('potential exit');
  9059.                 6: write('xdoor, key=',p_door_key(objreq));
  9060.                 7: begin
  9061.                     write('timed exit, now ');
  9062.                     if cycle_open then
  9063.                         write('open')
  9064.                     else
  9065.                         write('closed');
  9066.                    end;
  9067.             end;
  9068.             if hidden <> 0 then
  9069.                 write(', hidden');
  9070.             if reqverb then
  9071.                 write(', reqverb');
  9072.             if not(autolook) then
  9073.                 write(', autolook off');
  9074.             if here.trapto = dir then
  9075.                 write(', trapdoor (',here.trapchance:1,'%)');
  9076.         end;
  9077.         writeln;
  9078.     end;
  9079. end;
  9080.  
  9081.  
  9082. procedure do_s_exits;
  9083. var
  9084.     i: integer;
  9085.     accept,one: boolean;    { accept is true if the particular exit is
  9086.                   an "accept" (other players may link there)
  9087.                   one means at least one exit was shown }
  9088.  
  9089. begin
  9090.     one := false;
  9091.     gethere;
  9092.  
  9093.     for i := 1 to maxexit do begin
  9094.         if (here.exits[i].toloc = 0) and (here.exits[i].kind = 5) then
  9095.             accept := true
  9096.         else
  9097.             accept := false;
  9098.  
  9099.         if (can_alter(i)) or (accept) then begin
  9100.             if not(one) then begin    { first time we do this then }
  9101.                 getnam;        { read room name list in }
  9102.                 freenam;
  9103.                 getobjnam;
  9104.                 freeobjnam;
  9105.             end;
  9106.             one := true;
  9107.             anal_exit(i);
  9108.         end;
  9109.     end;
  9110.  
  9111.     if not(one) then
  9112.         writeln('There are no exits here which you may inspect.');
  9113. end;
  9114.  
  9115.  
  9116. procedure do_s_object(s: string);
  9117. var
  9118.     n: integer;
  9119.     x: objectrec;
  9120.  
  9121. begin
  9122.     if length(s) = 0 then begin
  9123.         grab_line('Object? ',s);
  9124.     end;
  9125.  
  9126.     if lookup_obj(n,s) then begin
  9127.         if obj_owner(n,TRUE) then begin
  9128.             write(obj_part(n),': ');
  9129.             write(objown.idents[n],' is owner');
  9130.             x := obj;
  9131.  
  9132.             if x.sticky then
  9133.                 write(', sticky');
  9134.             if x.getobjreq > 0 then
  9135.                 write(', ',obj_part(x.getobjreq),' required to get');
  9136.             if x.useobjreq > 0 then
  9137.                 write(', ',obj_part(x.useobjreq),' required to use');
  9138.             if x.uselocreq > 0 then begin
  9139.                 getnam;
  9140.                 freenam;
  9141.                 write(', used only in ',nam.idents[x.uselocreq]);
  9142.             end;
  9143.             if x.usealias <> '' then begin
  9144.                 write(', use="',x.usealias,'"');
  9145.                 if x.reqalias then
  9146.                     write(' (required)');
  9147.             end;
  9148.  
  9149.             writeln;
  9150.         end else
  9151.             writeln('You are not allowed to see the internals of that object.');
  9152.     end else
  9153.         writeln('There is no such object.');
  9154. end;
  9155.  
  9156.  
  9157. procedure do_s_details;
  9158. var
  9159.     i: integer;
  9160.     one: boolean;
  9161.  
  9162. begin
  9163.     gethere;
  9164.     one := false;
  9165.     for i := 1 to maxdetail do
  9166.         if (here.detail[i] <> '') and (here.detaildesc[i] <> 0) then begin
  9167.             if not(one) then begin
  9168.                 one := true;
  9169.                 writeln('Details here that you may inspect:');
  9170.             end;
  9171.             writeln('    ',here.detail[i]);
  9172.         end;
  9173.     if not(one) then
  9174.         writeln('There are no details of this room that you can inspect.');
  9175. end;
  9176.  
  9177. procedure do_s_help;
  9178.  
  9179. begin
  9180.     writeln;
  9181.     writeln('Exits             Lists exits you can inspect here');
  9182.     writeln('Object            Show internals of an object');
  9183.     writeln('Details           Show details you can look at in this room');
  9184.     writeln;
  9185. end;
  9186.  
  9187.  
  9188. procedure s_show(n: integer;s: string);
  9189.  
  9190. begin
  9191.     case n of
  9192.         s_exits: do_s_exits;
  9193.         s_object: do_s_object(s);
  9194.         s_quest: do_s_help;
  9195.         s_details: do_s_details;
  9196.     end;
  9197. end;
  9198.  
  9199.  
  9200. procedure do_y_altmsg;
  9201. var
  9202.     newdsc: integer;
  9203.  
  9204. begin
  9205.     if is_owner then begin
  9206.         gethere;
  9207.         newdsc := here.xmsg2;
  9208.         writeln('[ Editing the alternate mystery message for this room ]');
  9209.         if edit_desc(newdsc) then begin
  9210.             getroom;
  9211.             here.xmsg2 := newdsc;
  9212.             putroom;
  9213.         end;
  9214.     end;
  9215. end;
  9216.  
  9217.  
  9218. procedure do_y_help;
  9219.  
  9220. begin
  9221.     writeln;
  9222.     writeln('Altmsg        Set the alternate mystery message block');
  9223.     writeln;
  9224. end;
  9225.  
  9226.  
  9227. procedure do_group1;
  9228. var
  9229.     grpnam: string;
  9230.     loc: integer;
  9231.     tmp: string;
  9232.     
  9233. begin
  9234.     if is_owner then begin
  9235.         gethere;
  9236.         if here.grploc1 = 0 then
  9237.             writeln('No primary group location set')
  9238.         else begin
  9239.             getnam;
  9240.             freenam;
  9241.             writeln('The primary group location is ',nam.idents[here.grploc1],'.');
  9242.             writeln('Descriptor string: [',here.grpnam1,']');
  9243.         end;
  9244.         writeln;
  9245.         writeln('Type * to turn off the primary group location');
  9246.         grab_line('Room name of primary group? ',grpnam);
  9247.         if length(grpnam) = 0 then
  9248.             writeln('No changes.')
  9249.         else if grpnam = '*' then begin
  9250.             getroom;
  9251.             here.grploc1 := 0;
  9252.             putroom;
  9253.         end else if lookup_room(loc,grpnam) then begin
  9254.             writeln('Enter the descriptive string.  It will be placed after player names.');
  9255.             writeln('Example:  Monster Manager is [descriptive string, instead of "here."]');
  9256.             writeln;
  9257.             grab_line('Enter string? ',tmp);
  9258.             if length(tmp) > shortlen then begin
  9259.                 writeln('Your string was truncated to ',shortlen:1,' characters.');
  9260.                 tmp := substr(tmp,1,shortlen);
  9261.             end;
  9262.             getroom;
  9263.             here.grploc1 := loc;
  9264.             here.grpnam1 := tmp;
  9265.             putroom;
  9266.         end else
  9267.             writeln('No such room.');
  9268.     end;
  9269. end;
  9270.  
  9271.  
  9272.  
  9273. procedure do_group2;
  9274. var
  9275.     grpnam: string;
  9276.     loc: integer;
  9277.     tmp: string;
  9278.     
  9279. begin
  9280.     if is_owner then begin
  9281.         gethere;
  9282.         if here.grploc2 = 0 then
  9283.             writeln('No secondary group location set')
  9284.         else begin
  9285.             getnam;
  9286.             freenam;
  9287.             writeln('The secondary group location is ',nam.idents[here.grploc1],'.');
  9288.             writeln('Descriptor string: [',here.grpnam1,']');
  9289.         end;
  9290.         writeln;
  9291.         writeln('Type * to turn off the secondary group location');
  9292.         grab_line('Room name of secondary group? ',grpnam);
  9293.         if length(grpnam) = 0 then
  9294.             writeln('No changes.')
  9295.         else if grpnam = '*' then begin
  9296.             getroom;
  9297.             here.grploc2 := 0;
  9298.             putroom;
  9299.         end else if lookup_room(loc,grpnam) then begin
  9300.             writeln('Enter the descriptive string.  It will be placed after player names.');
  9301.             writeln('Example:  Monster Manager is [descriptive string, instead of "here."]');
  9302.             writeln;
  9303.             grab_line('Enter string? ',tmp);
  9304.             if length(tmp) > shortlen then begin
  9305.                 writeln('Your string was truncated to ',shortlen:1,' characters.');
  9306.                 tmp := substr(tmp,1,shortlen);
  9307.             end;
  9308.             getroom;
  9309.             here.grploc2 := loc;
  9310.             here.grpnam2 := tmp;
  9311.             putroom;
  9312.         end else
  9313.             writeln('No such room.');
  9314.     end;
  9315. end;
  9316.  
  9317.  
  9318. procedure s_set(n: integer;s: string);
  9319.  
  9320. begin
  9321.     case n of
  9322.         y_quest: do_y_help;
  9323.         y_altmsg: do_y_altmsg;
  9324.         y_group1: do_group1;
  9325.         y_group2: do_group2;
  9326.     end;
  9327. end;
  9328.  
  9329.  
  9330. procedure do_show(s: string);
  9331. var
  9332.     n: integer;
  9333.     cmd: string;
  9334.  
  9335. begin
  9336.     cmd := bite(s);
  9337.     if length(cmd) = 0 then
  9338.         grab_line('Show what attribute? (type ? for a list) ',cmd);
  9339.  
  9340.     if length(cmd) = 0 then
  9341.     else if lookup_show(n,cmd) then
  9342.         s_show(n,s)
  9343.     else
  9344.         writeln('Invalid show option, type SHOW ? for a list.');
  9345. end;
  9346.  
  9347.  
  9348. procedure do_set(s: string);
  9349. var
  9350.     n: integer;
  9351.     cmd: string;
  9352.  
  9353. begin
  9354.     cmd := bite(s);
  9355.     if length(cmd) = 0 then
  9356.         grab_line('Set what attribute? (type ? for a list) ',cmd);
  9357.  
  9358.     if length(cmd) = 0 then
  9359.     else if lookup_set(n,cmd) then
  9360.         s_set(n,s)
  9361.     else
  9362.         writeln('Invalid set option, type SET ? for a list.');
  9363. end;
  9364.  
  9365.  
  9366. procedure parser;
  9367. var
  9368.     s: string;
  9369.     cmd: string;
  9370.     n: integer;
  9371.     dummybool: boolean;
  9372.  
  9373. begin
  9374.    repeat
  9375.     grab_line('> ',s);
  9376.     s := slead(s);
  9377.    until length(s) > 0;
  9378.  
  9379.     if s = '.' then
  9380.         s := oldcmd
  9381.     else
  9382.         oldcmd := s;
  9383.  
  9384.     if (s[1]='''') and (length(s) > 1) then
  9385.         do_say(substr(s,2,length(s)-1))
  9386.     else begin
  9387.         cmd := bite(s);
  9388.         case lookup_cmd(cmd) of
  9389. { try exit alias }    error:begin
  9390.                 if (lookup_alias(n,cmd)) or
  9391.                    (lookup_dir(n,cmd)) then begin
  9392.                     do_go(cmd);
  9393.                 end else
  9394.                     writeln('Bad command, type ? for a list.');
  9395.             end;
  9396.  
  9397.             setnam: do_setname(s);
  9398.             help,quest: show_help;
  9399.             quit: done := true;
  9400.             c_l,look: do_look(s);
  9401.             go: do_go(s,FALSE);    { FALSE = dir not a verb }
  9402.             form: do_form(s);
  9403.             link: do_link(s);
  9404.             unlink: do_unlink(s);
  9405.             poof: do_poof(s);
  9406.             desc: do_describe(s);
  9407.             say: do_say(s);
  9408.             c_rooms: do_rooms(s);
  9409.             c_claim: do_claim(s);
  9410.             c_disown: do_disown(s);
  9411.             c_public: do_public(s);
  9412.             c_accept: do_accept(s);
  9413.             c_refuse: do_refuse(s);
  9414.             c_zap: do_zap(s);
  9415.  
  9416.             c_north,c_n,
  9417.             c_south,c_s,
  9418.             c_east,c_e,
  9419.             c_west,c_w,
  9420.             c_up,c_u,
  9421.             c_down,c_d: do_go(cmd);
  9422.  
  9423.             c_who: do_who;
  9424.             c_custom: do_custom(s);
  9425.             c_search: do_search(s);
  9426.             c_system: do_system(s);
  9427.             c_hide: do_hide(s);
  9428.             c_unhide: do_unhide(s);
  9429.             c_punch: do_punch(s);
  9430.             c_ping: do_ping(s);
  9431.             c_create: do_makeobj(s);
  9432.             c_get: do_get(s);
  9433.             c_drop: do_drop(s);
  9434.             c_i,c_inv: do_inv(s);
  9435.             c_whois: do_whois(s);
  9436.             c_players: do_players(s);
  9437.             c_health: do_health(s);
  9438.             c_duplicate: do_duplicate(s);
  9439.             c_version: do_version(s);
  9440.             c_objects: do_objects;
  9441.             c_self: do_self(s);
  9442.             c_use: do_use(s);
  9443.             c_whisper: do_whisper(s);
  9444.             c_wield: do_wield(s);
  9445.             c_brief: do_brief;
  9446.             c_wear: do_wear(s);
  9447.             c_destroy: do_destroy(s);
  9448.             c_relink: do_relink(s);
  9449.             c_unmake: do_unmake(s);
  9450.             c_show: do_show(s);
  9451.             c_set: do_set(s);
  9452.  
  9453.             dbg: begin
  9454.                 debug := not(debug);
  9455.                 if debug then
  9456.                     writeln('Debugging is on.')
  9457.                 else
  9458.                     writeln('Debugging is off.');
  9459.                  end;
  9460.             otherwise begin
  9461.                 writeln('%Parser error, bad return from lookup');
  9462.             end;
  9463.         end;
  9464.         clear_command;
  9465.     end;
  9466. end;
  9467.  
  9468.  
  9469.  
  9470. procedure init;
  9471. var
  9472.     i: integer;
  9473.  
  9474. begin
  9475.     rndcycle := 0;
  9476.     location := 1;        { Great Hall }
  9477.         
  9478.     mywield := 0;        { not initially wearing or weilding any weapon }
  9479.     mywear := 0;
  9480.     myhealth := 7;        { how healthy they are to start }
  9481.     healthcycle := 0;    { pretty much meaningless at the start }
  9482.  
  9483.     userid := lowcase(get_userid);
  9484.     if (userid = MM_userid) then begin
  9485.         myname := 'Monster Manager';
  9486.         privd := true;
  9487.     end else if (userid = MVM_userid) then begin
  9488.         privd := true;
  9489.         myname := 'Vice Manager';
  9490.     end else if (userid = FAUST_userid) then begin
  9491.         privd := true;
  9492.     end else begin
  9493.         myname := lowcase(userid);
  9494.         myname[1] := chr( ord('A') + (ord(myname[1]) - ord('a'))   );
  9495.         privd := false;
  9496.     end;
  9497.  
  9498.     numcmds:= 66;
  9499.  
  9500.     show[s_exits] := 'exits';
  9501.     show[s_object] := 'object';
  9502.     show[s_quest] := '?';
  9503.     show[s_details] := 'details';
  9504.     numshow := 4;
  9505.  
  9506.     setkey[y_quest] := '?';
  9507.     setkey[y_altmsg] := 'altmsg';
  9508.     setkey[y_group1] := 'group1';
  9509.     setkey[y_group2] := 'group2';
  9510.     numset := 4;
  9511.  
  9512.     numspells := 0;
  9513.  
  9514.     open(roomfile,root+'ROOMS.MON',access_method := direct,
  9515.         sharing := readwrite,
  9516.         history := unknown);
  9517.     open(namfile,root+'NAMS.MON',access_method := direct,
  9518.         sharing := readwrite,
  9519.         history := unknown);
  9520.     open(eventfile,root+'EVENTS.MON',access_method := direct,
  9521.         sharing := readwrite,
  9522.         history := unknown);
  9523.     open(descfile,root+'DESC.MON',access_method := direct,
  9524.         sharing := readwrite,
  9525.         history := unknown);
  9526.     open(indexfile,root+'INDEX.MON',access_method := direct,
  9527.         sharing := readwrite,
  9528.         history := unknown);
  9529.     open(linefile,root+'LINE.MON',access_method := direct,
  9530.         sharing := readwrite,
  9531.         history := unknown);
  9532.     open(intfile,root+'INTFILE.MON',access_method := direct,
  9533.         sharing := readwrite,
  9534.         history := unknown);
  9535.     open(objfile,root+'OBJECTS.MON',access_method := direct,
  9536.         sharing := readwrite,
  9537.         history := unknown);
  9538.     open(spellfile,root+'SPELLS.MON',access_method := direct,
  9539.         sharing := readwrite,
  9540.         history := unknown);
  9541. end;
  9542.  
  9543.  
  9544. procedure prestart;
  9545. var
  9546.     s: string;
  9547.  
  9548. begin
  9549.     write('Welcome to Monster!  Hit return to start: ');
  9550.     readln(s);
  9551.     writeln;
  9552.     writeln;
  9553.     if length(s) > 0 then
  9554.         special(lowcase(s));
  9555. end;
  9556.  
  9557.  
  9558. procedure welcome_back(var mylog: integer);
  9559. var
  9560.     tmp: string;
  9561.     sdate,stime: shortstring;
  9562.  
  9563. begin
  9564.     getdate;
  9565.     freedate;
  9566.  
  9567.     write('Welcome back, ',myname,'.');
  9568.     if length(myname) > 18 then
  9569.         writeln;
  9570.  
  9571.     write('  Your last play was on');
  9572.  
  9573.     if length(adate.idents[mylog]) < 11 then begin
  9574.         writeln(' ???');
  9575.     end else begin
  9576.         sdate := substr(adate.idents[mylog],1,11);    { extract the date }
  9577.         if length(adate.idents[mylog]) = 19 then
  9578.             stime := substr(adate.idents[mylog],13,7)
  9579.         else
  9580.             stime := '???';
  9581.  
  9582.         if sdate[1] = ' ' then
  9583.             tmp := sdate
  9584.         else
  9585.             tmp := ' ' + sdate;
  9586.  
  9587.         if stime[1] = ' ' then
  9588.             tmp := tmp + ' at' + stime
  9589.         else
  9590.             tmp := tmp + ' at ' + stime;
  9591.         writeln(tmp,'.');
  9592.     end;
  9593.     writeln;
  9594. end;
  9595.  
  9596.  
  9597. function loc_ping:boolean;
  9598. var
  9599.     i: integer;
  9600.     found: boolean;
  9601.  
  9602. begin
  9603.     inmem := false;
  9604.     gethere;
  9605.  
  9606.     i := 1;
  9607.     found := false;
  9608.  
  9609.         { first get the slot that the supposed "zombie" is in }
  9610.     while (not found) and (i <= maxpeople) do begin
  9611.         if here.people[i].name = myname then
  9612.             found := true
  9613.         else
  9614.             i := i + 1;
  9615.     end;
  9616.  
  9617.     myslot := 0;    { setup for ping_player }
  9618.  
  9619.     if found then begin
  9620.         setevent;
  9621.         loc_ping := ping_player(i,TRUE);  { TRUE = silent operation }
  9622.     end else
  9623.         loc_ping := true;
  9624.             { well, if we can't find them, let's assume
  9625.               that they're not in any room records, so they're
  9626.               ok . . . Let's hope... }
  9627. end;
  9628.  
  9629.  
  9630.  
  9631. { attempt to fix the player using loc_ping if the database incorrectly
  9632.   shows someone playing who isn' playing }
  9633.  
  9634. function fix_player:boolean;
  9635. var
  9636.     ok: boolean;
  9637.  
  9638. begin
  9639.     writeln('There may have been some trouble the last time you played.');
  9640.     writeln('Trying to fix it . . .');
  9641.     if loc_ping then begin
  9642.         writeln('All should be fixed now.');
  9643.         writeln;
  9644.         fix_player := true;
  9645.     end else begin
  9646.         writeln('Either someone else is playing Monster on your account, or something is');
  9647.         writeln('very wrong with the database.');
  9648.         writeln;
  9649.         fix_player := false;
  9650.     end;
  9651. end;
  9652.  
  9653.  
  9654. function revive_player(var mylog: integer): boolean;
  9655. var
  9656.     ok: boolean;
  9657.     i,n: integer;
  9658.  
  9659. begin
  9660.     if exact_user(mylog,userid) then begin    { player has played before }
  9661.         getint(N_LOCATION);
  9662.         freeint;
  9663.         location := anint.int[mylog];    { Retrieve their old loc }
  9664.  
  9665.         getpers;
  9666.         freepers;
  9667.         myname := pers.idents[mylog];    { Retrieve old personal name }
  9668.  
  9669.         getint(N_EXPERIENCE);
  9670.         freeint;
  9671.         myexperience := anint.int[mylog];
  9672.  
  9673.         getint(N_SELF);
  9674.         freeint;
  9675.         myself := anint.int[mylog];
  9676.  
  9677.         getindex(I_ASLEEP);
  9678.         freeindex;
  9679.  
  9680.         if indx.free[mylog] then begin
  9681.                 { if player is asleep, all is well }
  9682.             ok := true;
  9683.         end else begin
  9684.                 { otherwise, there is one of two possibilities:
  9685.                     1) someone on the same account is
  9686.                        playing Monster
  9687.                     2) his last play terminated abnormally
  9688.                 }
  9689.             ok := fix_player;
  9690.         end;
  9691.  
  9692.         if ok then
  9693.             welcome_back(mylog);
  9694.  
  9695.     end else begin    { must allocate a log block for the player }
  9696.         if alloc_log(mylog) then begin
  9697.  
  9698.             writeln('Welcome to Monster, ',myname,'!');
  9699.             writeln('You will start in the Great Hall.');
  9700.             writeln;
  9701.  
  9702.             { Store their userid }
  9703.             getuser;
  9704.             user.idents[mylog] := lowcase(userid);
  9705.             putuser;
  9706.  
  9707.             { Set their initial location }
  9708.             getint(N_LOCATION);
  9709.             anint.int[mylog] := 1;    { Start out in Great Hall }
  9710.             putint;
  9711.             location := 1;
  9712.  
  9713.             getint(N_EXPERIENCE);
  9714.             anint.int[mylog] := 0;
  9715.             putint;
  9716.             myexperience := 0;
  9717.  
  9718.             getint(N_SELF);
  9719.             anint.int[mylog] := 0;
  9720.             putint;
  9721.             myself := 0;
  9722.  
  9723.                 { initialize the record containing the
  9724.                   level of each spell they have to start;
  9725.                   all start at zero; since the spellfile is
  9726.                   directly parallel with mylog, we can hack
  9727.                   init it here without dealing with SYSTEM }
  9728.  
  9729.             locate(spellfile,mylog);
  9730.             for i := 1 to maxspells do
  9731.                 spellfile^.level[i] := 0;
  9732.             spellfile^.recnum := mylog;
  9733.             put(spellfile);
  9734.  
  9735.             ok := true;
  9736.         end else
  9737.             ok := false;
  9738.     end;
  9739.  
  9740.     if ok then begin { Successful, MYLOG is my log slot }
  9741.  
  9742.         { Wake up the player }
  9743.         getindex(I_ASLEEP);
  9744.         indx.free[mylog] := false;    { I'm NOT asleep now }
  9745.         putindex;
  9746.  
  9747.         { Set the "last date of play" }
  9748.         getdate;
  9749.         adate.idents[mylog] := sysdate + ' ' + systime;
  9750.         putdate;
  9751.     end else
  9752.         writeln('There is no place for you in Monster.  Contact the Monster Manager.');
  9753.     revive_player := ok;
  9754. end;
  9755.  
  9756.  
  9757. function enter_universe:boolean;
  9758. var
  9759.     orignam: string;
  9760.     dummy,i: integer;
  9761.     ok: boolean;
  9762.  
  9763. begin
  9764.  
  9765.  
  9766.         { take MYNAME given to us by init or revive_player and make
  9767.           sure it's unique.  If it isn't tack _1, _2, etc onto it 
  9768.           until it is.  Code must come before alloc_log, or there
  9769.           will be an invalid pers record in there cause we aren't in yet
  9770.         }
  9771.         orignam := myname;
  9772.         i := 0;
  9773.         repeat    { tack _n onto pers name until a unique one is found }
  9774.             ok := true;
  9775.  
  9776. {*** Should this use exact_pers instead?  Is this a copy of exact_pers code? }
  9777.  
  9778.             if lookup_pers(dummy,myname) then
  9779.                 if lowcase(pers.idents[dummy]) = lowcase(myname) then begin
  9780.                     ok := false;
  9781.                     i := i + 1;
  9782.                     writev(myname,orignam,'_',i:1);
  9783.                 end;
  9784.         until ok;
  9785.  
  9786.  
  9787.  
  9788.     if revive_player(mylog) then begin
  9789.     if put_token(location,myslot) then begin
  9790.         getpers;
  9791.         pers.idents[mylog] := myname;
  9792.         putpers;
  9793.  
  9794.         enter_universe := true;
  9795.         log_begin(location);
  9796.         setevent;
  9797.         do_look;
  9798.     end else begin
  9799.         writeln('put_token failed.');
  9800.         enter_universe := false;
  9801.     end;
  9802.     end else begin
  9803.         writeln('revive_player failed.');
  9804.         enter_universe := false;
  9805.     end;
  9806. end;
  9807.  
  9808. procedure leave_universe;
  9809. var
  9810.     diddrop: boolean;
  9811.  
  9812. begin
  9813.     diddrop := drop_everything;
  9814.     take_token(myslot,location);
  9815.     log_quit(location,diddrop);
  9816.     do_endplay(mylog);
  9817.  
  9818.     writeln('You vanish in a brilliant burst of multicolored light.');
  9819.     if diddrop then
  9820.         writeln('All of your belongings drop to the ground.');
  9821. end;
  9822.  
  9823.  
  9824. begin
  9825.     done := false;
  9826.     setup_guts;
  9827.     init;
  9828.     prestart;
  9829.     if not(done) then begin
  9830.         if enter_universe then begin
  9831.             repeat
  9832.                 parser;
  9833.             until done;
  9834.             leave_universe;
  9835.         end else
  9836.             writeln('You attempt to enter the Monster universe, but a strange force repels you.');
  9837.     end;
  9838.     finish_guts;
  9839. end.
  9840.  
  9841.  
  9842. { Notes to other who may inherit this program:
  9843.  
  9844.     Change all occurances in this file of dolpher to the account which
  9845.     you will use for maintenance of this program.  That account will
  9846.     have special administrative powers.
  9847.  
  9848.     This program uses several data files.  These files are in a directory
  9849.     specified by the variable root in procedure init.  In my implementation,
  9850.     I have a default ACL on the directory allowing everyone READ and WRITE
  9851.     access to the files created in that directory.  Whoever plays the game
  9852.     must be able to write to these data files.
  9853.  
  9854.  
  9855. Written by Rich Skrenta, 1988.
  9856.  
  9857.  
  9858.  
  9859.  
  9860. Brief program organization overview:
  9861. ------------------------------------
  9862.  
  9863. Monster's Shared Files:
  9864.  
  9865. Monster uses several shared files for communication.
  9866. Each shared file is accessed within Monster by a group of 3 procedures of the
  9867. form:    getX(), freeX and putX.
  9868.  
  9869. getX takes an integer and attempts to get and lock that record from the
  9870. appropriate data file.  If it encounters a "collision", it waits a short
  9871. random amount of time and tries again.  After maxerr collisions it prints
  9872. a deadlock warning message.
  9873.  
  9874. If data is to be read but not changed, a freeX should immediately follow
  9875. the getX so that other Monster processes can access the record.  If the
  9876. record is to be written then a putX must eventually follow the getX.
  9877.  
  9878.  
  9879. Monster's Record Allocation:
  9880.  
  9881. Monster dynamically allocates some resources such as description blocks and
  9882. lines and player log entries.  The allocation is from a bitmap.  I chose a
  9883. bitmap over a linked list to make the multiuser access to the database
  9884. more stable.  A particular resource (such as log entries) will have a
  9885. particular bitmap in the file INDEXFILE.  A getindex(I_LOG) will retrieve
  9886. the bitmap for it.  
  9887.  
  9888. Actually allocation and deallocation is done through the group of functions
  9889. alloc_X and delete_X.  If alloc_X returns true, the allocation was successful,
  9890. and the integer parameter is the number of the block allocated.
  9891.  
  9892. The top available record in each group is stored in indexrec.  To increase
  9893. the top, the new records must be initially written so that garbage data is
  9894. not in them and the getX routines can locate them.  This can be done with
  9895. the addX(n) group of routines, which add capacity to resources.
  9896.  
  9897.  
  9898.  
  9899. Parsing in Monster:
  9900.  
  9901. The main parser(s) use a first-unique-characters method to lookup command
  9902. keywords and parameters.  The format of these functions is lookup_x(n,s).
  9903. If it returns true, it successfully found an unambiguous match to string s.
  9904. The integer index will be in n.
  9905.  
  9906. If an unambiguating match is needed (for example, if someone makes a new room,
  9907. the match to see if the name exists shouldn't disambiguate), the group of
  9908. routines exact_X(n,s) are called.  They function similarly to lookup_x(n,s).
  9909.  
  9910. The customization subsystems and the editor use very primitive parsers
  9911. which only use first character match and integer arguments.
  9912.  
  9913.  
  9914.  
  9915. Asynchronous events in Monster:
  9916.  
  9917. When someone comes into a room, the other players in that room need
  9918. to be notified, even if they might be typing a command on their terminal.
  9919.  
  9920. This is done in a two part process (producer/consumer problem):
  9921.  
  9922. When an event takes place, the player's Monster that caused the event
  9923. makes a call to log_event.  Parameters include the slot of the sender (which
  9924. person in the room caused the event), the actual event that occurred
  9925. (E_something) and parameters.  Log_event works by sticking the event
  9926. into a circular buffer associated with the room (room may be specified on
  9927. log_event).
  9928.  
  9929. Note: there is not an event record for every room; instead, the event
  9930.       record used is  ROOM # mod ACTUAL NUMBER of EVENT RECORDS
  9931.  
  9932. The other half of the process occurrs when a player's Monster calls
  9933. grab_line to get some input.  Grab line looks for keystrokes, and if
  9934. there are none, it calls checkevent and then sleeps for a short time
  9935. (.1 - .2 seconds).  Checkevent loads the event record associated with this
  9936. room and compare's the player's buffer pointer with the record's buffer
  9937. pointer.  If they are different, checkevent bites off events and sends them
  9938. to handle_event until there are no more events to be processed.  Checkevent
  9939. ignores events logged by it's own player.
  9940.  
  9941.  
  9942. }
  9943.